Zelda Classic Coverage Report


Directory: src/
File: src/guys.cpp
Date: 2022-11-29 03:53:21
Exec Total Coverage
Lines: 1665 11478 14.5%
Functions: 99 422 23.5%
Branches: 1198 14546 8.2%

Line Branch Exec Source
1 //--------------------------------------------------------
2 // Zelda Classic
3 // by Jeremy Craner, 1999-2000
4 //
5 // guys.cc
6 //
7 // "Guys" code (and other related stuff) for zelda.cc
8 //
9 //--------------------------------------------------------
10
11 #include "precompiled.h" //always first
12
13 #include <string.h>
14 #include <stdio.h>
15 #include "base/zc_alleg.h"
16 11 #include "guys.h"
17 #include "zelda.h"
18 #include "base/zsys.h"
19 #include "maps.h"
20 #include "hero.h"
21 #include "subscr.h"
22 #include "ffscript.h"
23 #include "gamedata.h"
24 #include "defdata.h"
25 #include "zscriptversion.h"
26 #include "particles.h"
27 #include "base/zc_math.h"
28 #include "slopes.h"
29 extern particle_list particles;
30
31 extern FFScript FFCore;
32 extern word item_doscript[256];
33 extern refInfo itemScriptData[256];
34 extern int32_t item_stack[256][MAX_SCRIPT_REGISTERS];
35 extern ZModule zcm;
36 extern HeroClass Hero;
37 extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations;
38 extern zinitdata zinit;
39
40 int32_t repaircharge=0;
41 bool adjustmagic=false;
42 bool learnslash=false;
43 int32_t wallm_load_clk=0;
44 int32_t sle_x,sle_y,sle_cnt,sle_clk=0;
45 int32_t vhead=0;
46 int32_t guycarryingitem=0;
47
48 char *guy_string[eMAXGUYS];
49
50 void never_return(int32_t index);
51 void playLevelMusic();
52
53 // If an enemy is this far out of the playing field, just remove it.
54 #define OUTOFBOUNDS ((int32_t)y>((isSideViewGravity() && canfall(id))?192:352) || y<-176 || x<-256 || x > 512)
55 //#define NEWOUTOFBOUNDS ((int32_t)y>32767 || y<-32767 || x<-32767 || x > 32767)
56 #define IGNORE_SIDEVIEW_PLATFORMS (editorflags & ENEMY_FLAG14)
57 #define OFFGRID_ENEMY (editorflags & ENEMY_FLAG15)
58
59 56 void do_fix(zfix& coord, int32_t val, bool nearest_half = false)
60 {
61 56 int32_t c = coord.getInt();
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if(nearest_half)
63 {
64
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (c < 0)
65 c -= val / 2;
66 56 else c += (val/2);
67 56 }
68 56 c -= c % val;
69 56 coord = c;
70 56 }
71
72 bool NEWOUTOFBOUNDS(zfix x, zfix y, zfix z)
73 {
74 return
75 (
76 (((int32_t)y) > FFCore.enemy_removal_point[spriteremovalY2])
77 || (((int32_t)y) < FFCore.enemy_removal_point[spriteremovalY1])
78 || (((int32_t)x) < FFCore.enemy_removal_point[spriteremovalX1])
79 || (((int32_t)x) > FFCore.enemy_removal_point[spriteremovalX2])
80 || (((int32_t)z) < FFCore.enemy_removal_point[spriteremovalZ1])
81 || (((int32_t)z) > FFCore.enemy_removal_point[spriteremovalZ2])
82 );
83 }
84
85 namespace
86 {
87 int32_t trapConstantHorizontalID;
88 int32_t trapConstantVerticalID;
89 int32_t trapLOSHorizontalID;
90 int32_t trapLOSVerticalID;
91 int32_t trapLOS4WayID;
92
93 int32_t cornerTrapID;
94 int32_t centerTrapID;
95
96 int32_t rockID;
97 int32_t zoraID;
98 int32_t statueID;
99 }
100
101 13 void identifyCFEnemies()
102 {
103 13 trapConstantHorizontalID=-1;
104 13 trapConstantVerticalID=-1;
105 13 trapLOSHorizontalID=-1;
106 13 trapLOSVerticalID=-1;
107 13 trapLOS4WayID=-1;
108 13 cornerTrapID=-1;
109 13 centerTrapID=-1;
110 13 rockID=-1;
111 13 zoraID=-1;
112 13 statueID=-1;
113
114
2/2
✓ Branch 0 taken 6656 times.
✓ Branch 1 taken 13 times.
6669 for(int32_t i=0; i<eMAXGUYS; i++)
115 {
116
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&cmbflag_trph) && trapLOSHorizontalID==-1)
117 13 trapLOSHorizontalID=i;
118
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&cmbflag_trpv) && trapLOSVerticalID==-1)
119 13 trapLOSVerticalID=i;
120
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&cmbflag_trp4) && trapLOS4WayID==-1)
121 13 trapLOS4WayID=i;
122
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&cmbflag_trplr) && trapConstantHorizontalID==-1)
123 13 trapConstantHorizontalID=i;
124
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&cmbflag_trpud) && trapConstantVerticalID==-1)
125 13 trapConstantVerticalID=i;
126
127
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&eneflag_trap) && cornerTrapID==-1)
128 13 cornerTrapID=i;
129
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&eneflag_trp2) && centerTrapID==-1)
130 13 centerTrapID=i;
131
132
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&eneflag_rock) && rockID==-1)
133 13 rockID=i;
134
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2&eneflag_zora) && zoraID==-1)
135 13 zoraID=i;
136
137
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
6656 if((guysbuf[i].flags2 & eneflag_fire) && statueID==-1)
138 13 statueID=i;
139 6656 }
140 13 }
141
142 int32_t random_layer_enemy()
143 {
144 int32_t cnt=count_layer_enemies();
145
146 if(cnt==0)
147 {
148 return eNONE;
149 }
150
151 int32_t ret=zc_oldrand()%cnt;
152 cnt=0;
153
154 for(int32_t i=0; i<6; ++i)
155 {
156 if(tmpscr->layermap[i]!=0)
157 {
158 mapscr *layerscreen=&TheMaps[(tmpscr->layermap[i]-1)*MAPSCRS]+tmpscr->layerscreen[i];
159
160 for(int32_t j=0; j<10; ++j)
161 {
162 if(layerscreen->enemy[j]>0&&layerscreen->enemy[j]<MAXGUYS)
163 {
164 if(cnt==ret)
165 {
166 return layerscreen->enemy[j];
167 }
168
169 ++cnt;
170 }
171 }
172 }
173 }
174
175 return eNONE;
176 }
177
178 int32_t count_layer_enemies()
179 {
180 int32_t cnt=0;
181
182 for(int32_t i=0; i<6; ++i)
183 {
184 if(tmpscr->layermap[i]!=0)
185 {
186 mapscr *layerscreen=&TheMaps[(tmpscr->layermap[i]-1)*MAPSCRS]+tmpscr->layerscreen[i];
187
188 for(int32_t j=0; j<10; ++j)
189 {
190 if(layerscreen->enemy[j]!=0)
191 {
192 ++cnt;
193 }
194 }
195 }
196 }
197
198 return cnt;
199 }
200
201 int32_t hero_on_wall()
202 {
203 zfix lx = Hero.getX();
204 zfix ly = Hero.getY();
205
206
207 //zprint2("hero_on_wall x is: %d\n", lx);
208 //zprint2("hero_on_wall y is: %d\n", ly);
209
210 if(lx>=48 && lx<=192)
211 {
212 if(ly==32) return up+1;
213
214 if(ly==128) return down+1;
215 }
216
217 if(ly>=48 && ly<=112)
218 {
219 if(lx==32) return left+1;
220
221 if(lx==208) return right+1;
222 }
223
224 return 0;
225 }
226
227 16 bool tooclose(int32_t x,int32_t y,int32_t d)
228 {
229
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 return (abs(int32_t(HeroX())-x)<d && abs(int32_t(HeroY())-y)<d);
230 }
231
232 bool enemy::overpit(enemy *e)
233 {
234 for ( int32_t q = 0; q < hxsz; ++q )
235 {
236 for ( int32_t q = 0; q < hysz; ++q )
237 {
238 //check every pixel of the hitbox
239 if ( ispitfall(x+q+hxofs, y+q+hyofs) )
240 {
241 //if the hitbox is over a pit, we can't land
242 return true;
243 }
244 }
245 }
246 return false;
247 }
248
249 bool enemy::shadow_overpit(enemy *e)
250 {
251 for ( int32_t q = 0; q < hxsz; ++q )
252 {
253 for ( int32_t q = 0; q < hysz; ++q )
254 {
255 //check every pixel of the hitbox
256 if ( ispitfall(x+q+hxofs, y+q+hyofs+hysz-2) )
257 {
258 //if the hitbox is over a pit, we can't land
259 return true;
260 }
261 }
262 }
263 return false;
264 }
265
266 // Returns true iff a combo type or flag precludes enemy movement.
267 168 bool enemy::groundblocked(int32_t dx, int32_t dy, bool isKB)
268 {
269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if(moveflags & FLAG_IGNORE_BLOCKFLAGS) return false;
270 168 int32_t c = COMBOTYPE(dx,dy);
271
3/4
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
224 bool pit_blocks = (!(moveflags & (FLAG_CAN_PITWALK|FLAG_ONLY_PITWALK)) && (!(moveflags & FLAG_CAN_PITFALL) || !isKB));
272
3/6
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
168 bool water_blocks = (!(moveflags & (FLAG_CAN_WATERWALK|FLAG_ONLY_WATERWALK|FLAG_ONLY_SHALLOW_WATERWALK)) && (!(moveflags & FLAG_CAN_WATERDROWN) || !isKB) && get_bit(quest_rules,qr_DROWN));
273
4/6
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
336 return c==cPIT || c==cPITB || c==cPITC ||
274
3/6
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
56 c==cPITD || c==cPITR || (pit_blocks && ispitfall(dx,dy)) ||
275 // Block enemies type and block enemies flags
276 combo_class_buf[c].block_enemies&1 ||
277
2/4
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
56 MAPFLAG(dx,dy)==mfNOENEMY || MAPCOMBOFLAG(dx,dy)==mfNOENEMY ||
278
2/4
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
56 MAPFLAG(dx,dy)==mfNOGROUNDENEMY || MAPCOMBOFLAG(dx,dy)==mfNOGROUNDENEMY ||
279 // Check for ladder-only combos which aren't dried water
280
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
112 (combo_class_buf[c].ladder_pass&1 && !iswater_type(c)) ||
281 // Check for drownable water
282
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
56 (water_blocks && !(isSideViewGravity()) && (iswaterex(MAPCOMBO(dx,dy), currmap, currscr, -1, dx, dy, false, false, true, false, false)));
283 56 }
284
285 // Returns true iff enemy is floating and blocked by a combo type or flag.
286 28 bool enemy::flyerblocked(int32_t dx, int32_t dy, int32_t special, bool isKB)
287 {
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if(moveflags & FLAG_IGNORE_BLOCKFLAGS) return false;
289
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
56 bool pit_blocks = (!(moveflags & FLAG_CAN_PITWALK) && (!(moveflags & FLAG_CAN_PITFALL) || !isKB));
290
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
56 bool water_blocks = (!(moveflags & FLAG_CAN_WATERWALK) && (!(moveflags & FLAG_CAN_WATERDROWN) || !isKB));
291
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 return ((special==spw_floater)&&
292 ((COMBOTYPE(dx,dy)==cNOFLYZONE)||
293 (combo_class_buf[COMBOTYPE(dx,dy)].block_enemies&4)||
294 (MAPFLAG(dx,dy)==mfNOENEMY)||
295 (MAPCOMBOFLAG(dx,dy)==mfNOENEMY)||
296 (water_blocks && iswaterex(MAPCOMBO(dx, dy), currmap, currscr, -1, dx,dy, false, false, true)) ||
297 (pit_blocks && ispitfall(dx,dy))));
298 28 }
299 // Returns true iff a combo type or flag precludes enemy movement.
300 4 bool groundblocked(int32_t dx, int32_t dy, guydata const& gd)
301 {
302 4 int32_t c = COMBOTYPE(dx,dy);
303 4 bool pit_blocks = !(gd.moveflags & FLAG_CAN_PITWALK);
304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 bool water_blocks = !(gd.moveflags & FLAG_CAN_WATERWALK) && get_bit(quest_rules,qr_DROWN);
305
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
16 return c==cPIT || c==cPITB || c==cPITC ||
306
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 c==cPITD || c==cPITR || (pit_blocks && ispitfall(dx,dy)) ||
307 // Block enemies type and block enemies flags
308 combo_class_buf[c].block_enemies&1 ||
309
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 MAPFLAG(dx,dy)==mfNOENEMY || MAPCOMBOFLAG(dx,dy)==mfNOENEMY ||
310
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 MAPFLAG(dx,dy)==mfNOGROUNDENEMY || MAPCOMBOFLAG(dx,dy)==mfNOGROUNDENEMY ||
311 // Check for ladder-only combos which aren't dried water
312
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 (combo_class_buf[c].ladder_pass&1 && !iswater_type(c)) ||
313 // Check for drownable water
314
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 (water_blocks && !(isSideViewGravity()) && (iswaterex(MAPCOMBO(dx,dy), currmap, currscr, -1, dx, dy, false, false, true)));
315 }
316
317 // Returns true iff enemy is floating and blocked by a combo type or flag.
318 bool flyerblocked(int32_t dx, int32_t dy, int32_t special, guydata const& gd)
319 {
320 bool pit_blocks = (!(gd.moveflags & FLAG_CAN_PITWALK) && !(gd.moveflags & FLAG_CAN_PITFALL));
321 bool water_blocks = !(gd.moveflags & FLAG_CAN_WATERWALK);
322 return ((special==spw_floater)&&
323 ((COMBOTYPE(dx,dy)==cNOFLYZONE)||
324 (combo_class_buf[COMBOTYPE(dx,dy)].block_enemies&4)||
325 (MAPFLAG(dx,dy)==mfNOENEMY)||
326 (MAPCOMBOFLAG(dx,dy)==mfNOENEMY)||
327 (water_blocks && iswaterex(MAPCOMBO(dx,dy), currmap, currscr, -1, dx, dy, false, false, true)) ||
328 (pit_blocks && ispitfall(dx,dy))));
329 }
330
331 /**********************************/
332 /******* Enemy Base Class *******/
333 /**********************************/
334
335 /* ROM data flags
336
337 */
338
339 eFire::eFire(eFire const & other, bool new_script_uid, bool clear_parent_script_UID):
340 //Struct Element Type Purpose
341 //sprite(other),
342 enemy(other),
343 clk4(other.clk4),
344 shield(other.shield)
345
346 {
347
348 //arrays
349
350 if(other.scrmem)
351 {
352 alloc_scriptmem();
353 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
354
355 scrmem->scriptData = other.scrmem->scriptData;
356 }
357 else scrmem = NULL;
358 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
359 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
360
361 for(int32_t i=0; i<edefLAST255; i++)
362 defense[i]=other.defense[i];
363 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
364 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
365
366 if(new_script_uid)
367 {
368 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
369 }
370 if(clear_parent_script_UID)
371 {
372 parent_script_UID = 0;
373 }
374 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
375 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
376
377 for ( int32_t q = 0; q < 8; q++ )
378 {
379 initD[q] = other.initD[q];
380 weap_initiald[q] = other.weap_initiald[q];
381 }
382 for ( int32_t q = 0; q < 2; q++ )
383 {
384 initA[q] = other.initA[q];
385 weap_initiala[q] = other.weap_initiala[q];
386 }
387 }
388
389 eOther::eOther(eOther const & other, bool new_script_uid, bool clear_parent_script_UID):
390 //Struct Element Type Purpose
391 //sprite(other),
392 enemy(other),
393 clk4(other.clk4),
394 shield(other.shield)
395
396 {
397
398 //arrays
399
400 if(other.scrmem)
401 {
402 alloc_scriptmem();
403 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
404
405 scrmem->scriptData = other.scrmem->scriptData;
406 }
407 else scrmem = NULL;
408 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
409 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
410
411 for(int32_t i=0; i<edefLAST255; i++)
412 defense[i]=other.defense[i];
413 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
414 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
415
416 if(new_script_uid)
417 {
418 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
419 }
420 if(clear_parent_script_UID)
421 {
422 parent_script_UID = 0;
423 }
424 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
425 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
426
427 for ( int32_t q = 0; q < 8; q++ )
428 {
429 initD[q] = other.initD[q];
430 weap_initiald[q] = other.weap_initiald[q];
431 }
432 for ( int32_t q = 0; q < 2; q++ )
433 {
434 initA[q] = other.initA[q];
435 weap_initiala[q] = other.weap_initiala[q];
436 }
437 }
438
439
440
441
442 eScript::eScript(eScript const & other, bool new_script_uid, bool clear_parent_script_UID):
443 //Struct Element Type Purpose
444 //sprite(other),
445 enemy(other),
446 clk4(other.clk4),
447 shield(other.shield)
448
449 {
450
451 //arrays
452
453 if(other.scrmem)
454 {
455 alloc_scriptmem();
456 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
457
458 scrmem->scriptData = other.scrmem->scriptData;
459 }
460 else scrmem = NULL;
461 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
462 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
463
464 for(int32_t i=0; i<edefLAST255; i++)
465 defense[i]=other.defense[i];
466 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
467 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
468
469 if(new_script_uid)
470 {
471 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
472 }
473 if(clear_parent_script_UID)
474 {
475 parent_script_UID = 0;
476 }
477 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
478 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
479
480 for ( int32_t q = 0; q < 8; q++ )
481 {
482 initD[q] = other.initD[q];
483 weap_initiald[q] = other.weap_initiald[q];
484 }
485 for ( int32_t q = 0; q < 2; q++ )
486 {
487 initA[q] = other.initA[q];
488 weap_initiala[q] = other.weap_initiala[q];
489 }
490 }
491
492 eFriendly::eFriendly(eFriendly const & other, bool new_script_uid, bool clear_parent_script_UID):
493 //Struct Element Type Purpose
494 //sprite(other),
495 enemy(other),
496 clk4(other.clk4),
497 shield(other.shield)
498
499 {
500
501 //arrays
502
503 if(other.scrmem)
504 {
505 alloc_scriptmem();
506 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
507
508 scrmem->scriptData = other.scrmem->scriptData;
509 }
510 else scrmem = NULL;
511 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
512 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
513
514 for(int32_t i=0; i<edefLAST255; i++)
515 defense[i]=other.defense[i];
516 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
517 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
518
519 if(new_script_uid)
520 {
521 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
522 }
523 if(clear_parent_script_UID)
524 {
525 parent_script_UID = 0;
526 }
527 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
528 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
529
530 for ( int32_t q = 0; q < 8; q++ )
531 {
532 initD[q] = other.initD[q];
533 weap_initiald[q] = other.weap_initiald[q];
534 }
535 for ( int32_t q = 0; q < 2; q++ )
536 {
537 initA[q] = other.initA[q];
538 weap_initiala[q] = other.weap_initiala[q];
539 }
540 }
541
542 eGhini::eGhini(eGhini const & other, bool new_script_uid, bool clear_parent_script_UID):
543 //Struct Element Type Purpose
544 //sprite(other),
545 enemy(other),
546 clk4(other.clk4),
547 ox(other.ox),
548 oy(other.oy),
549 c(other.c)
550
551 {
552
553 //arrays
554
555 if(other.scrmem)
556 {
557 alloc_scriptmem();
558 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
559
560 scrmem->scriptData = other.scrmem->scriptData;
561 }
562 else scrmem = NULL;
563 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
564 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
565
566 for(int32_t i=0; i<edefLAST255; i++)
567 defense[i]=other.defense[i];
568 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
569 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
570
571 if(new_script_uid)
572 {
573 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
574 }
575 if(clear_parent_script_UID)
576 {
577 parent_script_UID = 0;
578 }
579 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
580 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
581
582 for ( int32_t q = 0; q < 8; q++ )
583 {
584 initD[q] = other.initD[q];
585 weap_initiald[q] = other.weap_initiald[q];
586 }
587 for ( int32_t q = 0; q < 2; q++ )
588 {
589 initA[q] = other.initA[q];
590 weap_initiala[q] = other.weap_initiala[q];
591 }
592 }
593
594 eTektite::eTektite(eTektite const & other, bool new_script_uid, bool clear_parent_script_UID):
595 //Struct Element Type Purpose
596 //sprite(other),
597 enemy(other),
598 old_y(other.old_y),
599 clk2start(other.clk2start),
600 cstart(other.cstart),
601 c(other.c)
602
603 {
604
605 //arrays
606
607 if(other.scrmem)
608 {
609 alloc_scriptmem();
610 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
611
612 scrmem->scriptData = other.scrmem->scriptData;
613 }
614 else scrmem = NULL;
615 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
616 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
617
618 for(int32_t i=0; i<edefLAST255; i++)
619 defense[i]=other.defense[i];
620 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
621 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
622
623 if(new_script_uid)
624 {
625 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
626 }
627 if(clear_parent_script_UID)
628 {
629 parent_script_UID = 0;
630 }
631 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
632 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
633
634 for ( int32_t q = 0; q < 8; q++ )
635 {
636 initD[q] = other.initD[q];
637 weap_initiald[q] = other.weap_initiald[q];
638 }
639 for ( int32_t q = 0; q < 2; q++ )
640 {
641 initA[q] = other.initA[q];
642 weap_initiala[q] = other.weap_initiala[q];
643 }
644 }
645
646 eItemFairy::eItemFairy(eItemFairy const & other, bool new_script_uid, bool clear_parent_script_UID):
647 //Struct Element Type Purpose
648 //sprite(other),
649 enemy(other)
650 {
651
652 //arrays
653
654 if(other.scrmem)
655 {
656 alloc_scriptmem();
657 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
658
659 scrmem->scriptData = other.scrmem->scriptData;
660 }
661 else scrmem = NULL;
662 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
663 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
664
665 for(int32_t i=0; i<edefLAST255; i++)
666 defense[i]=other.defense[i];
667 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
668 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
669
670 if(new_script_uid)
671 {
672 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
673 }
674 if(clear_parent_script_UID)
675 {
676 parent_script_UID = 0;
677 }
678 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
679 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
680
681 for ( int32_t q = 0; q < 8; q++ )
682 {
683 initD[q] = other.initD[q];
684 weap_initiald[q] = other.weap_initiald[q];
685 }
686 for ( int32_t q = 0; q < 2; q++ )
687 {
688 initA[q] = other.initA[q];
689 weap_initiala[q] = other.weap_initiala[q];
690 }
691 }
692
693 ePeahat::ePeahat(ePeahat const & other, bool new_script_uid, bool clear_parent_script_UID):
694 //Struct Element Type Purpose
695 //sprite(other),
696 enemy(other),
697 ox(other.ox),
698 oy(other.oy),
699 c(other.c)
700 {
701
702 //arrays
703
704 if(other.scrmem)
705 {
706 alloc_scriptmem();
707 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
708
709 scrmem->scriptData = other.scrmem->scriptData;
710 }
711 else scrmem = NULL;
712 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
713 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
714
715 for(int32_t i=0; i<edefLAST255; i++)
716 defense[i]=other.defense[i];
717 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
718 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
719
720 if(new_script_uid)
721 {
722 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
723 }
724 if(clear_parent_script_UID)
725 {
726 parent_script_UID = 0;
727 }
728 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
729 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
730
731 for ( int32_t q = 0; q < 8; q++ )
732 {
733 initD[q] = other.initD[q];
734 weap_initiald[q] = other.weap_initiald[q];
735 }
736 for ( int32_t q = 0; q < 2; q++ )
737 {
738 initA[q] = other.initA[q];
739 weap_initiala[q] = other.weap_initiala[q];
740 }
741 }
742
743 eLeever::eLeever(eLeever const & other, bool new_script_uid, bool clear_parent_script_UID):
744 //Struct Element Type Purpose
745 //sprite(other),
746 enemy(other),
747 temprule(other.temprule)
748 {
749
750 //arrays
751
752 if(other.scrmem)
753 {
754 alloc_scriptmem();
755 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
756
757 scrmem->scriptData = other.scrmem->scriptData;
758 }
759 else scrmem = NULL;
760 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
761 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
762
763 for(int32_t i=0; i<edefLAST255; i++)
764 defense[i]=other.defense[i];
765 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
766 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
767
768 if(new_script_uid)
769 {
770 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
771 }
772 if(clear_parent_script_UID)
773 {
774 parent_script_UID = 0;
775 }
776 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
777 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
778
779 for ( int32_t q = 0; q < 8; q++ )
780 {
781 initD[q] = other.initD[q];
782 weap_initiald[q] = other.weap_initiald[q];
783 }
784 for ( int32_t q = 0; q < 2; q++ )
785 {
786 initA[q] = other.initA[q];
787 weap_initiala[q] = other.weap_initiala[q];
788 }
789 }
790
791 eWallM::eWallM(eWallM const & other, bool new_script_uid, bool clear_parent_script_UID):
792 //Struct Element Type Purpose
793 //sprite(other),
794 enemy(other)
795 {
796
797 //arrays
798
799 if(other.scrmem)
800 {
801 alloc_scriptmem();
802 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
803
804 scrmem->scriptData = other.scrmem->scriptData;
805 }
806 else scrmem = NULL;
807 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
808 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
809
810 for(int32_t i=0; i<edefLAST255; i++)
811 defense[i]=other.defense[i];
812 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
813 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
814
815 if(new_script_uid)
816 {
817 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
818 }
819 if(clear_parent_script_UID)
820 {
821 parent_script_UID = 0;
822 }
823 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
824 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
825
826 for ( int32_t q = 0; q < 8; q++ )
827 {
828 initD[q] = other.initD[q];
829 weap_initiald[q] = other.weap_initiald[q];
830 }
831 for ( int32_t q = 0; q < 2; q++ )
832 {
833 initA[q] = other.initA[q];
834 weap_initiala[q] = other.weap_initiala[q];
835 }
836 }
837
838 eStalfos::eStalfos(eStalfos const & other, bool new_script_uid, bool clear_parent_script_UID):
839 //Struct Element Type Purpose
840 //sprite(other),
841 enemy(other),
842 clk4(other.clk4),
843 clk5(other.clk5),
844 fired(other.fired),
845 shield(other.shield),
846 dashing(other.dashing),
847 multishot(other.multishot),
848 fy(other.fy),
849 shadowdistance(other.shadowdistance)
850 {
851
852 //arrays
853
854 if(other.scrmem)
855 {
856 alloc_scriptmem();
857 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
858
859 scrmem->scriptData = other.scrmem->scriptData;
860 }
861 else scrmem = NULL;
862 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
863 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
864
865 for(int32_t i=0; i<edefLAST255; i++)
866 defense[i]=other.defense[i];
867 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
868 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
869
870 if(new_script_uid)
871 {
872 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
873 }
874 if(clear_parent_script_UID)
875 {
876 parent_script_UID = 0;
877 }
878 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
879 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
880
881 for ( int32_t q = 0; q < 8; q++ )
882 {
883 initD[q] = other.initD[q];
884 weap_initiald[q] = other.weap_initiald[q];
885 }
886 for ( int32_t q = 0; q < 2; q++ )
887 {
888 initA[q] = other.initA[q];
889 weap_initiala[q] = other.weap_initiala[q];
890 }
891 }
892
893 eZora::eZora(eZora const & other, bool new_script_uid, bool clear_parent_script_UID):
894 //Struct Element Type Purpose
895 //sprite(other),
896 enemy(other)
897 {
898
899 //arrays
900
901 if(other.scrmem)
902 {
903 alloc_scriptmem();
904 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
905
906 scrmem->scriptData = other.scrmem->scriptData;
907 }
908 else scrmem = NULL;
909 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
910 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
911
912 for(int32_t i=0; i<edefLAST255; i++)
913 defense[i]=other.defense[i];
914 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
915 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
916
917 if(new_script_uid)
918 {
919 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
920 }
921 if(clear_parent_script_UID)
922 {
923 parent_script_UID = 0;
924 }
925 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
926 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
927
928 for ( int32_t q = 0; q < 8; q++ )
929 {
930 initD[q] = other.initD[q];
931 weap_initiald[q] = other.weap_initiald[q];
932 }
933 for ( int32_t q = 0; q < 2; q++ )
934 {
935 initA[q] = other.initA[q];
936 weap_initiala[q] = other.weap_initiala[q];
937 }
938 }
939
940 eSpinTile::eSpinTile(eSpinTile const & other, bool new_script_uid, bool clear_parent_script_UID):
941 //Struct Element Type Purpose
942 //sprite(other),
943 enemy(other)
944 {
945
946 //arrays
947
948 if(other.scrmem)
949 {
950 alloc_scriptmem();
951 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
952
953 scrmem->scriptData = other.scrmem->scriptData;
954 }
955 else scrmem = NULL;
956 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
957 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
958
959 for(int32_t i=0; i<edefLAST255; i++)
960 defense[i]=other.defense[i];
961 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
962 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
963
964 if(new_script_uid)
965 {
966 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
967 }
968 if(clear_parent_script_UID)
969 {
970 parent_script_UID = 0;
971 }
972 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
973 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
974
975 for ( int32_t q = 0; q < 8; q++ )
976 {
977 initD[q] = other.initD[q];
978 weap_initiald[q] = other.weap_initiald[q];
979 }
980 for ( int32_t q = 0; q < 2; q++ )
981 {
982 initA[q] = other.initA[q];
983 weap_initiala[q] = other.weap_initiala[q];
984 }
985 }
986
987 eNPC::eNPC(eNPC const & other, bool new_script_uid, bool clear_parent_script_UID):
988 //Struct Element Type Purpose
989 //sprite(other),
990 enemy(other)
991 {
992
993 //arrays
994
995 if(other.scrmem)
996 {
997 alloc_scriptmem();
998 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
999
1000 scrmem->scriptData = other.scrmem->scriptData;
1001 }
1002 else scrmem = NULL;
1003 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1004 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1005
1006 for(int32_t i=0; i<edefLAST255; i++)
1007 defense[i]=other.defense[i];
1008 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1009 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1010
1011 if(new_script_uid)
1012 {
1013 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1014 }
1015 if(clear_parent_script_UID)
1016 {
1017 parent_script_UID = 0;
1018 }
1019 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1020 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1021
1022 for ( int32_t q = 0; q < 8; q++ )
1023 {
1024 initD[q] = other.initD[q];
1025 weap_initiald[q] = other.weap_initiald[q];
1026 }
1027 for ( int32_t q = 0; q < 2; q++ )
1028 {
1029 initA[q] = other.initA[q];
1030 weap_initiala[q] = other.weap_initiala[q];
1031 }
1032 }
1033
1034 eTrigger::eTrigger(eTrigger const & other, bool new_script_uid, bool clear_parent_script_UID):
1035 //Struct Element Type Purpose
1036 //sprite(other),
1037 enemy(other)
1038 {
1039
1040 //arrays
1041
1042 if(other.scrmem)
1043 {
1044 alloc_scriptmem();
1045 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1046
1047 scrmem->scriptData = other.scrmem->scriptData;
1048 }
1049 else scrmem = NULL;
1050 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1051 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1052
1053 for(int32_t i=0; i<edefLAST255; i++)
1054 defense[i]=other.defense[i];
1055 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1056 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1057
1058 if(new_script_uid)
1059 {
1060 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1061 }
1062 if(clear_parent_script_UID)
1063 {
1064 parent_script_UID = 0;
1065 }
1066 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1067 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1068
1069 for ( int32_t q = 0; q < 8; q++ )
1070 {
1071 initD[q] = other.initD[q];
1072 weap_initiald[q] = other.weap_initiald[q];
1073 }
1074 for ( int32_t q = 0; q < 2; q++ )
1075 {
1076 initA[q] = other.initA[q];
1077 weap_initiala[q] = other.weap_initiala[q];
1078 }
1079 }
1080
1081 eProjectile::eProjectile(eProjectile const & other, bool new_script_uid, bool clear_parent_script_UID):
1082 //Struct Element Type Purpose
1083 //sprite(other),
1084 enemy(other),
1085 minRange(other.minRange)
1086 {
1087
1088 //arrays
1089
1090 if(other.scrmem)
1091 {
1092 alloc_scriptmem();
1093 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1094
1095 scrmem->scriptData = other.scrmem->scriptData;
1096 }
1097 else scrmem = NULL;
1098 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1099 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1100
1101 for(int32_t i=0; i<edefLAST255; i++)
1102 defense[i]=other.defense[i];
1103 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1104 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1105
1106 if(new_script_uid)
1107 {
1108 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1109 }
1110 if(clear_parent_script_UID)
1111 {
1112 parent_script_UID = 0;
1113 }
1114 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1115 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1116
1117 for ( int32_t q = 0; q < 8; q++ )
1118 {
1119 initD[q] = other.initD[q];
1120 weap_initiald[q] = other.weap_initiald[q];
1121 }
1122 for ( int32_t q = 0; q < 2; q++ )
1123 {
1124 initA[q] = other.initA[q];
1125 weap_initiala[q] = other.weap_initiala[q];
1126 }
1127 }
1128
1129 eBoulder::eBoulder(eBoulder const & other, bool new_script_uid, bool clear_parent_script_UID):
1130 //Struct Element Type Purpose
1131 //sprite(other),
1132 enemy(other)
1133 {
1134
1135 //arrays
1136
1137 if(other.scrmem)
1138 {
1139 alloc_scriptmem();
1140 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1141
1142 scrmem->scriptData = other.scrmem->scriptData;
1143 }
1144 else scrmem = NULL;
1145 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1146 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1147
1148 for(int32_t i=0; i<edefLAST255; i++)
1149 defense[i]=other.defense[i];
1150 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1151 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1152
1153 if(new_script_uid)
1154 {
1155 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1156 }
1157 if(clear_parent_script_UID)
1158 {
1159 parent_script_UID = 0;
1160 }
1161 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1162 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1163
1164 for ( int32_t q = 0; q < 8; q++ )
1165 {
1166 initD[q] = other.initD[q];
1167 weap_initiald[q] = other.weap_initiald[q];
1168 }
1169 for ( int32_t q = 0; q < 2; q++ )
1170 {
1171 initA[q] = other.initA[q];
1172 weap_initiala[q] = other.weap_initiala[q];
1173 }
1174 }
1175
1176 eRock::eRock(eRock const & other, bool new_script_uid, bool clear_parent_script_UID):
1177 //Struct Element Type Purpose
1178 //sprite(other),
1179 enemy(other)
1180 {
1181
1182 //arrays
1183
1184 if(other.scrmem)
1185 {
1186 alloc_scriptmem();
1187 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1188
1189 scrmem->scriptData = other.scrmem->scriptData;
1190 }
1191 else scrmem = NULL;
1192 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1193 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1194
1195 for(int32_t i=0; i<edefLAST255; i++)
1196 defense[i]=other.defense[i];
1197 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1198 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1199
1200 if(new_script_uid)
1201 {
1202 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1203 }
1204 if(clear_parent_script_UID)
1205 {
1206 parent_script_UID = 0;
1207 }
1208 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1209 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1210
1211 for ( int32_t q = 0; q < 8; q++ )
1212 {
1213 initD[q] = other.initD[q];
1214 weap_initiald[q] = other.weap_initiald[q];
1215 }
1216 for ( int32_t q = 0; q < 2; q++ )
1217 {
1218 initA[q] = other.initA[q];
1219 weap_initiala[q] = other.weap_initiala[q];
1220 }
1221 }
1222
1223 eTrap2::eTrap2(eTrap2 const & other, bool new_script_uid, bool clear_parent_script_UID):
1224 //Struct Element Type Purpose
1225 //sprite(other),
1226 enemy(other)
1227 {
1228
1229 //arrays
1230
1231 if(other.scrmem)
1232 {
1233 alloc_scriptmem();
1234 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1235
1236 scrmem->scriptData = other.scrmem->scriptData;
1237 }
1238 else scrmem = NULL;
1239 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1240 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1241
1242 for(int32_t i=0; i<edefLAST255; i++)
1243 defense[i]=other.defense[i];
1244 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1245 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1246
1247 if(new_script_uid)
1248 {
1249 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1250 }
1251 if(clear_parent_script_UID)
1252 {
1253 parent_script_UID = 0;
1254 }
1255 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1256 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1257
1258 for ( int32_t q = 0; q < 8; q++ )
1259 {
1260 initD[q] = other.initD[q];
1261 weap_initiald[q] = other.weap_initiald[q];
1262 }
1263 for ( int32_t q = 0; q < 2; q++ )
1264 {
1265 initA[q] = other.initA[q];
1266 weap_initiala[q] = other.weap_initiala[q];
1267 }
1268 }
1269
1270 eTrap::eTrap(eTrap const & other, bool new_script_uid, bool clear_parent_script_UID):
1271 //Struct Element Type Purpose
1272 //sprite(other),
1273 enemy(other),
1274 ox(other.ox),
1275 oy(other.oy)
1276 {
1277
1278 //arrays
1279
1280 if(other.scrmem)
1281 {
1282 alloc_scriptmem();
1283 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1284
1285 scrmem->scriptData = other.scrmem->scriptData;
1286 }
1287 else scrmem = NULL;
1288 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1289 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1290
1291 for(int32_t i=0; i<edefLAST255; i++)
1292 defense[i]=other.defense[i];
1293 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1294 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1295
1296 if(new_script_uid)
1297 {
1298 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1299 }
1300 if(clear_parent_script_UID)
1301 {
1302 parent_script_UID = 0;
1303 }
1304 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1305 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1306
1307 for ( int32_t q = 0; q < 8; q++ )
1308 {
1309 initD[q] = other.initD[q];
1310 weap_initiald[q] = other.weap_initiald[q];
1311 }
1312 for ( int32_t q = 0; q < 2; q++ )
1313 {
1314 initA[q] = other.initA[q];
1315 weap_initiala[q] = other.weap_initiala[q];
1316 }
1317 }
1318
1319
1320
1321
1322 eKeese::eKeese(eKeese const & other, bool new_script_uid, bool clear_parent_script_UID):
1323 //Struct Element Type Purpose
1324 //sprite(other),
1325 enemy(other),
1326 ox(other.ox),
1327 c(other.c),
1328 clk4(other.clk4),
1329 oy(other.oy)
1330 {
1331
1332 //arrays
1333
1334 if(other.scrmem)
1335 {
1336 alloc_scriptmem();
1337 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1338
1339 scrmem->scriptData = other.scrmem->scriptData;
1340 }
1341 else scrmem = NULL;
1342 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1343 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1344
1345 for(int32_t i=0; i<edefLAST255; i++)
1346 defense[i]=other.defense[i];
1347 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1348 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1349
1350 if(new_script_uid)
1351 {
1352 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1353 }
1354 if(clear_parent_script_UID)
1355 {
1356 parent_script_UID = 0;
1357 }
1358 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1359 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1360
1361 for ( int32_t q = 0; q < 8; q++ )
1362 {
1363 initD[q] = other.initD[q];
1364 weap_initiald[q] = other.weap_initiald[q];
1365 }
1366 for ( int32_t q = 0; q < 2; q++ )
1367 {
1368 initA[q] = other.initA[q];
1369 weap_initiala[q] = other.weap_initiala[q];
1370 }
1371 }
1372
1373 eWizzrobe::eWizzrobe(eWizzrobe const & other, bool new_script_uid, bool clear_parent_script_UID):
1374 //Struct Element Type Purpose
1375 //sprite(other),
1376 enemy(other),
1377 charging(other.charging),
1378 firing(other.firing),
1379 fclk(other.fclk)
1380 {
1381
1382 //arrays
1383
1384 if(other.scrmem)
1385 {
1386 alloc_scriptmem();
1387 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1388
1389 scrmem->scriptData = other.scrmem->scriptData;
1390 }
1391 else scrmem = NULL;
1392 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1393 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1394
1395 for(int32_t i=0; i<edefLAST255; i++)
1396 defense[i]=other.defense[i];
1397 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1398 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1399
1400 if(new_script_uid)
1401 {
1402 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1403 }
1404 if(clear_parent_script_UID)
1405 {
1406 parent_script_UID = 0;
1407 }
1408 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1409 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1410
1411 for ( int32_t q = 0; q < 8; q++ )
1412 {
1413 initD[q] = other.initD[q];
1414 weap_initiald[q] = other.weap_initiald[q];
1415 }
1416 for ( int32_t q = 0; q < 2; q++ )
1417 {
1418 initA[q] = other.initA[q];
1419 weap_initiala[q] = other.weap_initiala[q];
1420 }
1421 }
1422
1423 eDodongo::eDodongo(eDodongo const & other, bool new_script_uid, bool clear_parent_script_UID):
1424 //Struct Element Type Purpose
1425 //sprite(other),
1426 enemy(other)
1427 {
1428
1429 //arrays
1430
1431 if(other.scrmem)
1432 {
1433 alloc_scriptmem();
1434 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1435
1436 scrmem->scriptData = other.scrmem->scriptData;
1437 }
1438 else scrmem = NULL;
1439 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1440 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1441
1442 for(int32_t i=0; i<edefLAST255; i++)
1443 defense[i]=other.defense[i];
1444 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1445 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1446
1447 if(new_script_uid)
1448 {
1449 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1450 }
1451 if(clear_parent_script_UID)
1452 {
1453 parent_script_UID = 0;
1454 }
1455 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1456 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1457
1458 for ( int32_t q = 0; q < 8; q++ )
1459 {
1460 initD[q] = other.initD[q];
1461 weap_initiald[q] = other.weap_initiald[q];
1462 }
1463 for ( int32_t q = 0; q < 2; q++ )
1464 {
1465 initA[q] = other.initA[q];
1466 weap_initiala[q] = other.weap_initiala[q];
1467 }
1468 }
1469
1470 eDodongo2::eDodongo2(eDodongo2 const & other, bool new_script_uid, bool clear_parent_script_UID):
1471 //Struct Element Type Purpose
1472 //sprite(other),
1473 enemy(other),
1474 previous_dir(other.previous_dir)
1475 {
1476
1477 //arrays
1478
1479 if(other.scrmem)
1480 {
1481 alloc_scriptmem();
1482 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1483
1484 scrmem->scriptData = other.scrmem->scriptData;
1485 }
1486 else scrmem = NULL;
1487 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1488 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1489
1490 for(int32_t i=0; i<edefLAST255; i++)
1491 defense[i]=other.defense[i];
1492 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1493 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1494
1495 if(new_script_uid)
1496 {
1497 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1498 }
1499 if(clear_parent_script_UID)
1500 {
1501 parent_script_UID = 0;
1502 }
1503 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1504 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1505
1506 for ( int32_t q = 0; q < 8; q++ )
1507 {
1508 initD[q] = other.initD[q];
1509 weap_initiald[q] = other.weap_initiald[q];
1510 }
1511 for ( int32_t q = 0; q < 2; q++ )
1512 {
1513 initA[q] = other.initA[q];
1514 weap_initiala[q] = other.weap_initiala[q];
1515 }
1516 }
1517
1518 eAquamentus::eAquamentus(eAquamentus const & other, bool new_script_uid, bool clear_parent_script_UID):
1519 //Struct Element Type Purpose
1520 //sprite(other),
1521 enemy(other),
1522 fbx(other.fbx),
1523 clk4(other.clk4)
1524 {
1525
1526 //arrays
1527
1528 if(other.scrmem)
1529 {
1530 alloc_scriptmem();
1531 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1532
1533 scrmem->scriptData = other.scrmem->scriptData;
1534 }
1535 else scrmem = NULL;
1536 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1537 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1538
1539 for(int32_t i=0; i<edefLAST255; i++)
1540 defense[i]=other.defense[i];
1541 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1542 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1543
1544 if(new_script_uid)
1545 {
1546 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1547 }
1548 if(clear_parent_script_UID)
1549 {
1550 parent_script_UID = 0;
1551 }
1552 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1553 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1554
1555 for ( int32_t q = 0; q < 8; q++ )
1556 {
1557 initD[q] = other.initD[q];
1558 weap_initiald[q] = other.weap_initiald[q];
1559 }
1560 for ( int32_t q = 0; q < 2; q++ )
1561 {
1562 initA[q] = other.initA[q];
1563 weap_initiala[q] = other.weap_initiala[q];
1564 }
1565 }
1566
1567 eGohma::eGohma(eGohma const & other, bool new_script_uid, bool clear_parent_script_UID):
1568 //Struct Element Type Purpose
1569 //sprite(other),
1570 enemy(other),
1571 clk4(other.clk4)
1572 {
1573
1574 //arrays
1575
1576 if(other.scrmem)
1577 {
1578 alloc_scriptmem();
1579 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1580
1581 scrmem->scriptData = other.scrmem->scriptData;
1582 }
1583 else scrmem = NULL;
1584 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1585 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1586
1587 for(int32_t i=0; i<edefLAST255; i++)
1588 defense[i]=other.defense[i];
1589 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1590 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1591
1592 if(new_script_uid)
1593 {
1594 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1595 }
1596 if(clear_parent_script_UID)
1597 {
1598 parent_script_UID = 0;
1599 }
1600 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1601 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1602
1603 for ( int32_t q = 0; q < 8; q++ )
1604 {
1605 initD[q] = other.initD[q];
1606 weap_initiald[q] = other.weap_initiald[q];
1607 }
1608 for ( int32_t q = 0; q < 2; q++ )
1609 {
1610 initA[q] = other.initA[q];
1611 weap_initiala[q] = other.weap_initiala[q];
1612 }
1613 }
1614
1615 eLilDig::eLilDig(eLilDig const & other, bool new_script_uid, bool clear_parent_script_UID):
1616 //Struct Element Type Purpose
1617 //sprite(other),
1618 enemy(other)
1619 {
1620
1621 //arrays
1622
1623 if(other.scrmem)
1624 {
1625 alloc_scriptmem();
1626 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1627
1628 scrmem->scriptData = other.scrmem->scriptData;
1629 }
1630 else scrmem = NULL;
1631 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1632 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1633
1634 for(int32_t i=0; i<edefLAST255; i++)
1635 defense[i]=other.defense[i];
1636 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1637 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1638
1639 if(new_script_uid)
1640 {
1641 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1642 }
1643 if(clear_parent_script_UID)
1644 {
1645 parent_script_UID = 0;
1646 }
1647 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1648 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1649
1650 for ( int32_t q = 0; q < 8; q++ )
1651 {
1652 initD[q] = other.initD[q];
1653 weap_initiald[q] = other.weap_initiald[q];
1654 }
1655 for ( int32_t q = 0; q < 2; q++ )
1656 {
1657 initA[q] = other.initA[q];
1658 weap_initiala[q] = other.weap_initiala[q];
1659 }
1660 }
1661
1662 eBigDig::eBigDig(eBigDig const & other, bool new_script_uid, bool clear_parent_script_UID):
1663 //Struct Element Type Purpose
1664 //sprite(other),
1665 enemy(other)
1666 {
1667
1668 //arrays
1669
1670 if(other.scrmem)
1671 {
1672 alloc_scriptmem();
1673 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1674
1675 scrmem->scriptData = other.scrmem->scriptData;
1676 }
1677 else scrmem = NULL;
1678 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1679 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1680
1681 for(int32_t i=0; i<edefLAST255; i++)
1682 defense[i]=other.defense[i];
1683 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1684 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1685
1686 if(new_script_uid)
1687 {
1688 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1689 }
1690 if(clear_parent_script_UID)
1691 {
1692 parent_script_UID = 0;
1693 }
1694 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1695 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1696
1697 for ( int32_t q = 0; q < 8; q++ )
1698 {
1699 initD[q] = other.initD[q];
1700 weap_initiald[q] = other.weap_initiald[q];
1701 }
1702 for ( int32_t q = 0; q < 2; q++ )
1703 {
1704 initA[q] = other.initA[q];
1705 weap_initiala[q] = other.weap_initiala[q];
1706 }
1707 }
1708
1709 eGanon::eGanon(eGanon const & other, bool new_script_uid, bool clear_parent_script_UID):
1710 //Struct Element Type Purpose
1711 //sprite(other),
1712 enemy(other),
1713 Stunclk(other.Stunclk)
1714
1715 {
1716
1717 //arrays
1718
1719 if(other.scrmem)
1720 {
1721 alloc_scriptmem();
1722 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1723
1724 scrmem->scriptData = other.scrmem->scriptData;
1725 }
1726 else scrmem = NULL;
1727 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1728 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1729
1730 for(int32_t i=0; i<edefLAST255; i++)
1731 defense[i]=other.defense[i];
1732 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1733 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1734
1735 if(new_script_uid)
1736 {
1737 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1738 }
1739 if(clear_parent_script_UID)
1740 {
1741 parent_script_UID = 0;
1742 }
1743 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1744 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1745
1746 for ( int32_t q = 0; q < 8; q++ )
1747 {
1748 initD[q] = other.initD[q];
1749 weap_initiald[q] = other.weap_initiald[q];
1750 }
1751 for ( int32_t q = 0; q < 2; q++ )
1752 {
1753 initA[q] = other.initA[q];
1754 weap_initiala[q] = other.weap_initiala[q];
1755 }
1756 }
1757
1758 eMoldorm::eMoldorm(eMoldorm const & other, bool new_script_uid, bool clear_parent_script_UID):
1759 //Struct Element Type Purpose
1760 //sprite(other),
1761 enemy(other),
1762 segcnt(other.segcnt),
1763 segid(other.segid)
1764
1765 {
1766
1767 //arrays
1768
1769 if(other.scrmem)
1770 {
1771 alloc_scriptmem();
1772 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1773
1774 scrmem->scriptData = other.scrmem->scriptData;
1775 }
1776 else scrmem = NULL;
1777 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1778 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1779
1780 for(int32_t i=0; i<edefLAST255; i++)
1781 defense[i]=other.defense[i];
1782 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1783 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1784
1785 if(new_script_uid)
1786 {
1787 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1788 }
1789 if(clear_parent_script_UID)
1790 {
1791 parent_script_UID = 0;
1792 }
1793 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1794 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1795
1796 for ( int32_t q = 0; q < 8; q++ )
1797 {
1798 initD[q] = other.initD[q];
1799 weap_initiald[q] = other.weap_initiald[q];
1800 }
1801 for ( int32_t q = 0; q < 2; q++ )
1802 {
1803 initA[q] = other.initA[q];
1804 weap_initiala[q] = other.weap_initiala[q];
1805 }
1806 }
1807
1808 esMoldorm::esMoldorm(esMoldorm const & other, bool new_script_uid, bool clear_parent_script_UID):
1809 //Struct Element Type Purpose
1810 //sprite(other),
1811 enemy(other),
1812 parentclk(other.parentclk)
1813 {
1814
1815 //arrays
1816
1817 if(other.scrmem)
1818 {
1819 alloc_scriptmem();
1820 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1821
1822 scrmem->scriptData = other.scrmem->scriptData;
1823 }
1824 else scrmem = NULL;
1825 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1826 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1827
1828 for(int32_t i=0; i<edefLAST255; i++)
1829 defense[i]=other.defense[i];
1830 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1831 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1832
1833 if(new_script_uid)
1834 {
1835 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1836 }
1837 if(clear_parent_script_UID)
1838 {
1839 parent_script_UID = 0;
1840 }
1841 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1842 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1843
1844 for ( int32_t q = 0; q < 8; q++ )
1845 {
1846 initD[q] = other.initD[q];
1847 weap_initiald[q] = other.weap_initiald[q];
1848 }
1849 for ( int32_t q = 0; q < 2; q++ )
1850 {
1851 initA[q] = other.initA[q];
1852 weap_initiala[q] = other.weap_initiala[q];
1853 }
1854 }
1855 /*
1856 eManhandla::eManhandla(eManhandla const & other, bool new_script_uid, bool clear_parent_script_UID):
1857 //Struct Element Type Purpose
1858 //sprite(other),
1859 enemy(other),
1860 armcnt(armcnt),
1861 adjusted(adjusted),
1862 arm[0](arm[0]),
1863 arm[1](arm[1]),
1864 arm[2](arm[2]),
1865 arm[3](arm[3]),
1866 arm[4](arm[4]),
1867 arm[5](arm[5]),
1868 arm[6](arm[6]),
1869 arm[7](arm[7])
1870 {
1871
1872 //arrays
1873 if(other.scrmem)
1874 {
1875 alloc_scriptmem();
1876 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1877
1878 scrmem->scriptData = other.scrmem->scriptData;
1879 }
1880 else scrmem = NULL;
1881 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1882 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1883
1884 for(int32_t i=0; i<edefLAST255; i++)
1885 defense[i]=other.defense[i];
1886 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1887 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1888
1889 if(new_script_uid)
1890 {
1891 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1892 }
1893 if(clear_parent_script_UID)
1894 {
1895 parent_script_UID = 0;
1896 }
1897 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1898 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1899
1900 for ( int32_t q = 0; q < 8; q++ )
1901 {
1902 initD[q] = other.initD[q];
1903 weap_initiald[q] = other.weap_initiald[q];
1904 }
1905 for ( int32_t q = 0; q < 2; q++ )
1906 {
1907 initA[q] = other.initA[q];
1908 weap_initiala[q] = other.weap_initiala[q];
1909 }
1910 }
1911
1912 esManhandla::esManhandla(esManhandla const & other, bool new_script_uid, bool clear_parent_script_UID):
1913 //Struct Element Type Purpose
1914 //sprite(other),
1915 enemy(other)
1916 {
1917
1918 //arrays
1919 if(other.scrmem)
1920 {
1921 alloc_scriptmem();
1922 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1923
1924 scrmem->scriptData = other.scrmem->scriptData;
1925 }
1926 else scrmem = NULL;
1927 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1928 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1929
1930 for(int32_t i=0; i<edefLAST255; i++)
1931 defense[i]=other.defense[i];
1932 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1933 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1934
1935 if(new_script_uid)
1936 {
1937 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1938 }
1939 if(clear_parent_script_UID)
1940 {
1941 parent_script_UID = 0;
1942 }
1943 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1944 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1945
1946 for ( int32_t q = 0; q < 8; q++ )
1947 {
1948 initD[q] = other.initD[q];
1949 weap_initiald[q] = other.weap_initiald[q];
1950 }
1951 for ( int32_t q = 0; q < 2; q++ )
1952 {
1953 initA[q] = other.initA[q];
1954 weap_initiala[q] = other.weap_initiala[q];
1955 }
1956 }
1957
1958 eGleeok::eGleeok(eGleeok const & other, bool new_script_uid, bool clear_parent_script_UID):
1959 //Struct Element Type Purpose
1960 //sprite(other),
1961 enemy(other),
1962 flameclk(flameclk),
1963 flamehead(flamehead),
1964 necktile(necktile)
1965
1966 {
1967
1968 //arrays
1969
1970 if(other.scrmem)
1971 {
1972 alloc_scriptmem();
1973 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
1974
1975 scrmem->scriptData = other.scrmem->scriptData;
1976 }
1977 else scrmem = NULL;
1978 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
1979 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
1980
1981 for(int32_t i=0; i<edefLAST255; i++)
1982 defense[i]=other.defense[i];
1983 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
1984 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
1985
1986 if(new_script_uid)
1987 {
1988 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
1989 }
1990 if(clear_parent_script_UID)
1991 {
1992 parent_script_UID = 0;
1993 }
1994 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
1995 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
1996
1997 for ( int32_t q = 0; q < 8; q++ )
1998 {
1999 initD[q] = other.initD[q];
2000 weap_initiald[q] = other.weap_initiald[q];
2001 }
2002 for ( int32_t q = 0; q < 2; q++ )
2003 {
2004 initA[q] = other.initA[q];
2005 weap_initiala[q] = other.weap_initiala[q];
2006 }
2007 }
2008
2009 esGleeok::esGleeok(esGleeok const & other, bool new_script_uid, bool clear_parent_script_UID):
2010 //Struct Element Type Purpose
2011 //sprite(other),
2012 enemy(other),
2013 headtile(headtile),
2014 flyingheadtile(flyingheadtile),
2015 necktile(necktile),
2016 xoffset(xoffset),
2017 yoffset(yoffset),
2018 nx(nx),
2019 ny(ny),
2020 nxoffset(nxoffset),
2021 nyoffset(nyoffset),
2022 parent(parent)
2023
2024 {
2025
2026 //arrays
2027
2028 if(other.scrmem)
2029 {
2030 alloc_scriptmem();
2031 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
2032
2033 scrmem->scriptData = other.scrmem->scriptData;
2034 }
2035 else scrmem = NULL;
2036 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
2037 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
2038
2039 //for ( int32_t q = 0; q < 255; q++ )
2040 //{
2041 // nx[q] = other.nx[q];
2042 // ny[q] = other.ny[q];
2043 // nxoffset[q] = other.nxoffset[q];
2044 // nyoffset[q] = other.nyoffset[q];
2045 //}
2046
2047 for(int32_t i=0; i<edefLAST255; i++)
2048 defense[i]=other.defense[i];
2049 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
2050 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
2051
2052 if(new_script_uid)
2053 {
2054 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2055 }
2056 if(clear_parent_script_UID)
2057 {
2058 parent_script_UID = 0;
2059 }
2060 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
2061 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
2062
2063 for ( int32_t q = 0; q < 8; q++ )
2064 {
2065 initD[q] = other.initD[q];
2066 weap_initiald[q] = other.weap_initiald[q];
2067 }
2068 for ( int32_t q = 0; q < 2; q++ )
2069 {
2070 initA[q] = other.initA[q];
2071 weap_initiala[q] = other.weap_initiala[q];
2072 }
2073 }
2074
2075 ePatra::ePatra(ePatra const & other, bool new_script_uid, bool clear_parent_script_UID):
2076 //Struct Element Type Purpose
2077 //sprite(other),
2078 enemy(other),
2079 flycnt(flycnt),
2080 flycnt2(flycnt2),
2081 loopcnt(loopcnt),
2082 lookat(lookat),
2083 circle_x(circle_x),
2084 circle_y(circle_y),
2085 temp_x(temp_x),
2086 temp_y(temp_y),
2087 adjusted(adjusted)
2088
2089 {
2090
2091 //arrays
2092
2093 if(other.scrmem)
2094 {
2095 alloc_scriptmem();
2096 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
2097
2098 scrmem->scriptData = other.scrmem->scriptData;
2099 }
2100 else scrmem = NULL;
2101 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
2102 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
2103
2104 for(int32_t i=0; i<edefLAST255; i++)
2105 defense[i]=other.defense[i];
2106 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
2107 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
2108
2109 if(new_script_uid)
2110 {
2111 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2112 }
2113 if(clear_parent_script_UID)
2114 {
2115 parent_script_UID = 0;
2116 }
2117 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
2118 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
2119
2120 for ( int32_t q = 0; q < 8; q++ )
2121 {
2122 initD[q] = other.initD[q];
2123 weap_initiald[q] = other.weap_initiald[q];
2124 }
2125 for ( int32_t q = 0; q < 2; q++ )
2126 {
2127 initA[q] = other.initA[q];
2128 weap_initiala[q] = other.weap_initiala[q];
2129 }
2130 }
2131
2132 ePatraBS::ePatraBS(ePatraBS const & other, bool new_script_uid, bool clear_parent_script_UID):
2133 //Struct Element Type Purpose
2134 //sprite(other),
2135 enemy(other),
2136 flycnt(flycnt),
2137 flycnt2(flycnt2),
2138 loopcnt(loopcnt),
2139 lookat(lookat),
2140 adjusted(adjusted)
2141
2142 {
2143
2144 //arrays
2145
2146 if(other.scrmem)
2147 {
2148 alloc_scriptmem();
2149 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
2150
2151 scrmem->scriptData = other.scrmem->scriptData;
2152 }
2153 else scrmem = NULL;
2154 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
2155 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
2156
2157 for(int32_t i=0; i<edefLAST255; i++)
2158 defense[i]=other.defense[i];
2159 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
2160 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
2161
2162 if(new_script_uid)
2163 {
2164 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2165 }
2166 if(clear_parent_script_UID)
2167 {
2168 parent_script_UID = 0;
2169 }
2170 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
2171 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
2172
2173 for ( int32_t q = 0; q < 8; q++ )
2174 {
2175 initD[q] = other.initD[q];
2176 weap_initiald[q] = other.weap_initiald[q];
2177 }
2178 for ( int32_t q = 0; q < 2; q++ )
2179 {
2180 initA[q] = other.initA[q];
2181 weap_initiala[q] = other.weap_initiala[q];
2182 }
2183 }
2184
2185 esPatra::esPatra(esPatra const & other, bool new_script_uid, bool clear_parent_script_UID):
2186 //Struct Element Type Purpose
2187 //sprite(other),
2188 enemy(other)
2189
2190 {
2191
2192 //arrays
2193
2194 if(other.scrmem)
2195 {
2196 alloc_scriptmem();
2197 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
2198
2199 scrmem->scriptData = other.scrmem->scriptData;
2200 }
2201 else scrmem = NULL;
2202 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
2203 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
2204
2205 for ( int32_t q = 0; q < 255; q++ )
2206 {
2207 nx[q] = other.nx[q];
2208 ny[q] = other.ny[q];
2209 nxoffset[q] = other.nxoffset[q];
2210 nyoffset[q] = other.nyoffset[q];
2211 }
2212
2213 for(int32_t i=0; i<edefLAST255; i++)
2214 defense[i]=other.defense[i];
2215 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
2216 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
2217
2218 if(new_script_uid)
2219 {
2220 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2221 }
2222 if(clear_parent_script_UID)
2223 {
2224 parent_script_UID = 0;
2225 }
2226 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
2227 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
2228
2229 for ( int32_t q = 0; q < 8; q++ )
2230 {
2231 initD[q] = other.initD[q];
2232 weap_initiald[q] = other.weap_initiald[q];
2233 }
2234 for ( int32_t q = 0; q < 2; q++ )
2235 {
2236 initA[q] = other.initA[q];
2237 weap_initiala[q] = other.weap_initiala[q];
2238 }
2239 }
2240
2241 esPatraBS::esPatraBS(esPatraBS const & other, bool new_script_uid, bool clear_parent_script_UID):
2242 //Struct Element Type Purpose
2243 //sprite(other),
2244 enemy(other)
2245
2246 {
2247
2248 //arrays
2249
2250 if(other.scrmem)
2251 {
2252 alloc_scriptmem();
2253 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
2254
2255 scrmem->scriptData = other.scrmem->scriptData;
2256 }
2257 else scrmem = NULL;
2258 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
2259 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
2260
2261 for ( int32_t q = 0; q < 255; q++ )
2262 {
2263 nx[q] = other.nx[q];
2264 ny[q] = other.ny[q];
2265 nxoffset[q] = other.nxoffset[q];
2266 nyoffset[q] = other.nyoffset[q];
2267 }
2268
2269 for(int32_t i=0; i<edefLAST255; i++)
2270 defense[i]=other.defense[i];
2271 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
2272 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
2273
2274 if(new_script_uid)
2275 {
2276 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2277 }
2278 if(clear_parent_script_UID)
2279 {
2280 parent_script_UID = 0;
2281 }
2282 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
2283 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
2284
2285 for ( int32_t q = 0; q < 8; q++ )
2286 {
2287 initD[q] = other.initD[q];
2288 weap_initiald[q] = other.weap_initiald[q];
2289 }
2290 for ( int32_t q = 0; q < 2; q++ )
2291 {
2292 initA[q] = other.initA[q];
2293 weap_initiala[q] = other.weap_initiala[q];
2294 }
2295 }
2296
2297 */
2298
2299
5/10
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 9 not taken.
45 enemy::enemy(zfix X,zfix Y,int32_t Id,int32_t Clk) : sprite()
2300 30 {
2301
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 x=X;
2302
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 y=Y;
2303 15 id=Id;
2304 15 clk=Clk;
2305
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 floor_y=y;
2306 15 ceiling=false;
2307 15 fading = misc = clk2 = clk3 = stunclk = hclk = sclk = superman = 0;
2308 15 grumble = movestatus = posframe = timer = ox = oy = 0;
2309
4/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
15 yofs = (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) - ((isSideViewGravity()) ? 0 : 2);
2310 15 did_armos=true;
2311 15 script_spawned=false;
2312
2313 15 d = guysbuf + (id & 0xFFF);
2314 15 hp = d->hp;
2315 15 starting_hp = hp;
2316 // cs = d->cset;
2317 //d variables
2318
2319 15 flags=d->flags;
2320 15 flags2=d->flags2;
2321 15 s_tile=d->s_tile; //secondary (additional) tile(s)
2322 15 family=d->family;
2323 15 dcset=d->cset;
2324 15 cs=dcset;
2325
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 anim=get_bit(quest_rules,qr_NEWENEMYTILES)?d->e_anim:d->anim;
2326 15 dp=d->dp;
2327 15 wdp=d->wdp;
2328 15 wpn=d->weapon;
2329 15 wpnsprite = d-> wpnsprite; //2.6 -Z
2330 15 rate=d->rate;
2331 15 hrate=d->hrate;
2332
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 dstep=d->step;
2333 15 homing=d->homing;
2334 15 dmisc1=d->misc1;
2335 15 dmisc2=d->misc2;
2336 15 dmisc3=d->misc3;
2337 15 dmisc4=d->misc4;
2338 15 dmisc5=d->misc5;
2339 15 dmisc6=d->misc6;
2340 15 dmisc7=d->misc7;
2341 15 dmisc8=d->misc8;
2342 15 dmisc9=d->misc9;
2343 15 dmisc10=d->misc10;
2344 15 dmisc11=d->misc11;
2345 15 dmisc12=d->misc12;
2346 15 dmisc13=d->misc13;
2347 15 dmisc14=d->misc14;
2348 15 dmisc15=d->misc15;
2349 15 dmisc16=d->misc16;
2350 15 dmisc17=d->misc17;
2351 15 dmisc18=d->misc18;
2352 15 dmisc19=d->misc19;
2353 15 dmisc20=d->misc20;
2354 15 dmisc21=d->misc21;
2355 15 dmisc22=d->misc22;
2356 15 dmisc23=d->misc23;
2357 15 dmisc24=d->misc24;
2358 15 dmisc25=d->misc25;
2359 15 dmisc26=d->misc26;
2360 15 dmisc27=d->misc27;
2361 15 dmisc28=d->misc28;
2362 15 dmisc29=d->misc29;
2363 15 dmisc30=d->misc30;
2364 15 dmisc31=d->misc31;
2365 15 dmisc32=d->misc32;
2366
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 if (get_bit(quest_rules, qr_BROKEN_ATTRIBUTE_31_32))
2367 {
2368 15 dmisc31 = dmisc32;
2369 15 dmisc32 = 0;
2370 15 }
2371 15 spr_shadow=d->spr_shadow;
2372 15 spr_death=d->spr_death;
2373 15 spr_spawn=d->spr_spawn;
2374
2375
2/2
✓ Branch 0 taken 615 times.
✓ Branch 1 taken 15 times.
630 for(int32_t i=0; i<edefLAST255; i++)
2376 615 defense[i]=d->defense[i];
2377
2378 15 bgsfx=d->bgsfx;
2379 15 hitsfx=d->hitsfx;
2380 15 deadsfx=d->deadsfx;
2381 15 bosspal=d->bosspal;
2382 15 parent_script_UID = 0;
2383
2384 15 frozentile = d->frozentile;
2385
2386 15 frozencset = d->frozencset;
2387 15 frozenclock = 0;
2388
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 15 times.
165 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = d->frozenmisc[q];
2389
2390
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 240 times.
255 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = 0;
2391 //firesfx = 0; //t.b.a -Z
2392 15 isCore = true; //t.b.a
2393 15 parentCore = 0; //t.b.a
2394
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2395
2396 15 firesfx = d->firesfx;
2397
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 15 times.
495 for ( int32_t q = 0; q < 32; q++ ) movement[q] = d->movement[q];
2398
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 15 times.
495 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = d->new_weapon[q];
2399
2400
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 script = (d->script >= 0) ? d->script : 0; //Dont assign invalid data.
2401 15 waitdraw = 0;
2402
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 weaponscript = (d->weaponscript >= 0) ? d->weaponscript : 0; //Dont assign invalid data.
2403
2404
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 15 times.
135 for ( int32_t q = 0; q < 8; q++ )
2405 {
2406 120 initD[q] = d->initD[q];
2407 //Z_scripterrlog("(enemy::enemy(zfix)): Loading weapon InitD[%d] to an enemy with a value of (%d)\n",q,d->weap_initiald[q]);
2408 120 weap_initiald[q] = d->weap_initiald[q];
2409 //al_trace("Guys.cpp: Assigning guy.initD[%d]: %d\n",q, d->initD.initD[q]);
2410 //al_trace("Guys.cpp: Assigning guy.initD[%d] from d->initD[%d]: %d\n",q,q, d->initD[q]);
2411 //al_trace("Guys.cpp: guy.initD[%d] is: %d\n",q, initD[q]);
2412 120 }
2413
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 15 times.
45 for ( int32_t q = 0; q < 2; q++ )
2414 {
2415 30 initA[q] = d->initA[q];
2416 30 weap_initiala[q] = d->weap_initiala[q];
2417 30 }
2418
2419 15 stickclk = 0;
2420 15 submerged = false;
2421 15 hitdir = -1;
2422 15 dialogue_str = 0; //set by spawn flags.
2423 15 editorflags = d->editorflags; //set by Enemy Editor
2424 //Set the drawing flag for this sprite.
2425
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if ( (editorflags&ENEMY_FLAG12) ) { drawflags |= sprdrawflagALWAYSOLDDRAWS; }
2426
2427
2428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(bosspal>-1)
2429 {
2430 loadpalset(csBOSS,pSprite(bosspal));
2431 }
2432
2433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(bgsfx>-1)
2434 {
2435 cont_sfx(bgsfx);
2436 }
2437
2438
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if(get_bit(quest_rules,qr_NEWENEMYTILES))
2439 {
2440 o_tile=d->e_tile;
2441 frate = d->e_frate;
2442 }
2443 else
2444 {
2445 15 o_tile=d->tile;
2446 15 frate = d->frate;
2447 }
2448
2449 15 tile=0; //init to 0 here, but set it later.
2450
2451 15 scripttile = -1;
2452 15 scriptflip = -1;
2453 15 do_animation = 1;
2454 15 immortal = false;
2455 15 noSlide = false;
2456 15 deathexstate = -1;
2457
2458 15 hashero=false;
2459
2460 // If they forgot the invisibility flag, here's another failsafe:
2461
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if(o_tile==0 && family!=eeSPINTILE)
2462 flags |= guy_invisible;
2463
2464 // step = d->step/100.0;
2465 // To preserve the odd step values for Keese & Gleeok heads. -L
2466
3/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15 if(dstep==62.0) dstep+=0.5;
2467
3/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15 else if(dstep==89) dstep-=1/9;
2468
2469
5/10
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 9 not taken.
15 step = zslongToFix(dstep*100);
2470
2471
2472 15 item_set = d->item_set;
2473 15 grumble = d->grumble;
2474
2475
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 if(frate == 0)
2476 1 frate = 256;
2477
2478 15 leader = itemguy = dying = scored = false;
2479 15 canfreeze = count_enemy = true;
2480 15 mainguy = !(flags & guy_doesntcount);
2481
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 dir = zc_oldrand()&3;
2482
2483 //2.6 Enemy Editor Hit and TIle Sizes
2484
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
15 if ( ((d->SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && d->txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
2485 //al_trace("->txsz:%i\n", d->txsz); Verified that this is setting the value. -Z
2486 // al_trace("Enemy txsz:%i\n", txsz);
2487
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
15 if ( ((d->SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && d->tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
2488
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && d->hxsz >= 0 ) hxsz = d->hxsz;
2489
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && d->hysz >= 0 ) hysz = d->hysz;
2490
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && d->hzsz >= 0 ) hzsz = d->hzsz;
2491
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if ( (d->SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
2492
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if ( (d->SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
2493 // if ( (d->SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = d->hzofs;
2494
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
2495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
2496 {
2497 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
2498 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
2499 }
2500
2501
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
15 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
2502
2503 15 SIZEflags = d->SIZEflags;
2504
2505
2/10
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
15 if((wpn==ewBomb || wpn==ewSBomb) && family!=eeOTHER && family!=eeFIRE && (family!=eeWALK || dmisc2 != e2tBOMBCHU))
2506 wpn = 0;
2507
2508 //tile should never be 0 after init --Z (failsafe)
2509
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
15 if (tile <= 0 && FFCore.getQuestHeaderInfo(vZelda) >= 0x255) {tile = o_tile;}
2510
2511 //Moveflags; for gravity and pit interaction
2512 15 moveflags = d->moveflags;
2513
3/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
15 if(!can_pitfall(false))
2514 {
2515 //Some enemies must not interact with pits. Force their flags, for sanity's sake.
2516 3 moveflags &= ~FLAG_CAN_PITFALL;
2517 3 moveflags &= ~FLAG_CAN_WATERDROWN;
2518 3 }
2519
2520
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 shieldCanBlock = get_bit(quest_rules,qr_GOHMA_UNDAMAGED_BUG)?true:false;
2521 15 }
2522
2523 //base clone constructor
2524
2525 enemy::enemy(enemy const & other, bool new_script_uid, bool clear_parent_script_UID):
2526 //Struct Element Type Purpose
2527 sprite(other),
2528 //x(other.x), //int32_t
2529 //y(other.y), //int32_t
2530 //id(other.id), //int32_t
2531 //clk(other.clk), //int32_t
2532 floor_y(other.floor_y), //int32_t
2533 fading(other.fading), //int32_t
2534 //misc(other.misc), //int32_t
2535 clk2(other.clk2), //int32_t
2536 clk3(other.clk3), //int32_t
2537 stunclk(other.stunclk), //int32_t
2538 hclk(other.hclk), //int32_t
2539 sclk(other.sclk), //int32_t
2540 superman(other.superman), //int32_t
2541 //grumble(other.grumble), //int32_t
2542 movestatus(other.movestatus), //int32_t
2543 posframe(other.posframe), //int32_t
2544 timer(other.timer), //int32_t
2545 ox(other.ox), //int32_t
2546 oy(other.oy), //int32_t
2547 //yofs(other.yofs), //int32_t
2548 did_armos(other.did_armos), //int32_t
2549 script_spawned(other.script_spawned), //int32_t
2550 d(other.d), //int32_t
2551 hp(other.hp), //int32_t
2552 starting_hp(other.starting_hp), //int32_t
2553 //flags(other.flags), //int32_t
2554
2555 flags2(other.flags2), //int32_t
2556 s_tile(other.s_tile), //int32_t
2557 family(other.family), //int32_t
2558 dcset(other.dcset), //int32_t
2559 //cs(other.cs), //int32_t
2560 anim(other.anim), //int32_t
2561 dp(other.dp), //int32_t
2562 wdp(other.wdp), //int32_t
2563 wpnsprite(other.wpnsprite), //int32_t
2564 rate(other.rate), //int32_t
2565 hrate(other.hrate), //int32_t
2566 dstep(other.dstep), //int32_t
2567
2568 homing(other.homing), //int32_t
2569 dmisc1(other.dmisc1), //int32_t
2570 dmisc2(other.dmisc2), //int32_t
2571 dmisc3(other.dmisc3), //int32_t
2572 dmisc4(other.dmisc4), //int32_t
2573 dmisc5(other.dmisc5), //int32_t
2574 dmisc6(other.dmisc6), //int32_t
2575 dmisc7(other.dmisc7), //int32_t
2576 dmisc8(other.dmisc8), //int32_t
2577 dmisc9(other.dmisc9), //int32_t
2578 dmisc10(other.dmisc10), //int32_t
2579 dmisc11(other.dmisc11), //int32_t
2580 dmisc12(other.dmisc12), //int32_t
2581 dmisc13(other.dmisc13), //int32_t
2582 dmisc14(other.dmisc14), //int32_t
2583 dmisc15(other.dmisc15), //int32_t
2584 dmisc16(other.dmisc16), //int32_t
2585 dmisc17(other.dmisc17), //int32_t
2586 dmisc18(other.dmisc18), //int32_t
2587 dmisc19(other.dmisc19), //int32_t
2588 dmisc20(other.dmisc20), //int32_t
2589 dmisc21(other.dmisc21), //int32_t
2590 dmisc22(other.dmisc22), //int32_t
2591 dmisc23(other.dmisc23), //int32_t
2592 dmisc24(other.dmisc24), //int32_t
2593 dmisc25(other.dmisc25), //int32_t
2594 dmisc26(other.dmisc26), //int32_t
2595 dmisc27(other.dmisc27), //int32_t
2596 dmisc28(other.dmisc28), //int32_t
2597 dmisc29(other.dmisc29), //int32_t
2598 dmisc30(other.dmisc30), //int32_t
2599 dmisc31(other.dmisc31), //int32_t
2600 dmisc32(other.dmisc32), //int32_t
2601 bgsfx(other.bgsfx), //int32_t
2602 hitsfx(other.hitsfx), //int32_t
2603 deadsfx(other.deadsfx), //int32_t
2604 bosspal(other.bosspal), //int32_t
2605 parent_script_UID(other.parent_script_UID), //int32_t
2606 frozentile(other.frozentile), //int32_t
2607 frozencset(other.frozencset), //int32_t
2608 frozenclock(other.frozenclock), //int32_t
2609 isCore(other.isCore), //int32_t
2610 parentCore(other.parentCore), //int32_t
2611 script_UID(other.script_UID), //int32_t
2612 firesfx(other.firesfx), //int32_t
2613 //script(other.script), //int32_t
2614 //waitdraw(other.waitdraw), //int32_t
2615 weaponscript(other.weaponscript), //int32_t
2616 stickclk(other.stickclk), //int32_t
2617 hitdir(other.hitdir), //int32_t
2618 submerged(other.submerged), //int32_t
2619
2620 dialogue_str(other.dialogue_str), //int32_t
2621 editorflags(other.editorflags), //int32_t
2622 //drawflags(other.drawflags), //int32_t
2623 o_tile(other.o_tile), //int32_t
2624 frate(other.frate), //int32_t
2625 //tile(other.tile), //int32_t
2626 //scripttile(other.scripttile), //int32_t
2627 //scriptflip(other.scriptflip), //int32_t
2628 //do_animation(other.do_animation), //int32_t
2629 immortal(other.immortal), //bool
2630 noSlide(other.noSlide), //bool
2631 deathexstate(other.deathexstate), //int32_t
2632 flags(other.flags), //int32_t
2633 step(other.step), //int32_t
2634
2635 item_set(other.item_set), //int32_t
2636 grumble(other.grumble), //int32_t
2637 leader(other.leader), //int32_t
2638 itemguy(other.itemguy), //int32_t
2639 dying(other.dying), //int32_t
2640 scored(other.scored), //int32_t
2641 //canfreeze(other.canfreeze), //int32_t
2642 count_enemy(other.count_enemy), //int32_t
2643 mainguy(other.mainguy), //int32_t
2644 //dir(other.dir), //int32_t
2645
2646 //txsz(other.txsz), //int32_t
2647 //tysz(other.tysz), //int32_t
2648 //hxsz(other.hxsz), //int32_t
2649 //hysz(other.hysz), //int32_t
2650 //hzsz(other.hzsz), //int32_t
2651 //hxofs(other.hxofs), //int32_t
2652 //hxofs(other.hxofs), //int32_t
2653 //xofs(other.xofs), //int32_t
2654 //yofs(other.yofs), //int32_t
2655 //hzofs(other.hzofs), //int32_t
2656 //zofs(other.zofs), //int32_t
2657
2658 wpn(other.wpn), //int32_t
2659 SIZEflags(other.SIZEflags), //int32_t
2660 hashero(other.hashero)
2661
2662 {
2663
2664 //arrays
2665
2666 if(other.scrmem)
2667 {
2668 alloc_scriptmem();
2669 memcpy(scrmem->stack, other.scrmem->stack, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
2670
2671 scrmem->scriptData = other.scrmem->scriptData;
2672 }
2673 else scrmem = NULL;
2674 //memset((refInfo)scriptData, 0xFFFF, sizeof(refInfo));
2675 //memset((refInfo)scriptData, other.scriptData, sizeof(refInfo));
2676
2677 for(int32_t i=0; i<edefLAST255; i++)
2678 defense[i]=other.defense[i];
2679 for ( int32_t q = 0; q < 10; q++ ) frozenmisc[q] = other.frozenmisc[q];
2680 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) hitby[q] = other.hitby[q];
2681
2682 if(new_script_uid)
2683 {
2684 script_UID = FFCore.GetScriptObjectUID(UID_TYPE_NPC); //This is used by child npcs.
2685 }
2686 if(clear_parent_script_UID)
2687 {
2688 parent_script_UID = 0;
2689 }
2690 for ( int32_t q = 0; q < 32; q++ ) movement[q] = other.movement[q];
2691 for ( int32_t q = 0; q < 32; q++ ) new_weapon[q] = other.new_weapon[q];
2692
2693 for ( int32_t q = 0; q < 8; q++ )
2694 {
2695 initD[q] = other.initD[q];
2696 weap_initiald[q] = other.weap_initiald[q];
2697 }
2698 for ( int32_t q = 0; q < 2; q++ )
2699 {
2700 initA[q] = other.initA[q];
2701 weap_initiala[q] = other.weap_initiala[q];
2702 }
2703 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
2704 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
2705 // al_trace("Enemy txsz:%i\n", txsz);
2706 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = tysz; if ( tysz > 1 ) extend = 3; }
2707 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = hxsz;
2708 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = hysz;
2709 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = hzsz;
2710 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = hxofs;
2711 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = hyofs;
2712 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
2713 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)xofs;
2714 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
2715 {
2716 yofs = (int32_t)yofs; //This seems to be setting to +48 or something with any value set?! -Z
2717 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
2718 }
2719
2720 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)zofs;
2721
2722
2723
2724
2725 }
2726
2727
2728 int32_t enemy::getScriptUID() { return script_UID; }
2729 void enemy::setScriptUID(int32_t new_id) { script_UID = new_id; }
2730 13 enemy::~enemy()
2731 13 {
2732
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 FFCore.deallocateAllArrays(SCRIPT_NPC, getUID());
2733 13 }
2734
2735
2736 bool enemy::is_move_paused()
2737 {
2738 return (clk<0 || dying || stunclk || watch || ceiling || frozenclock || fallclk || drownclk);
2739 }
2740
2741 bool enemy::scr_walkflag(int32_t dx,int32_t dy,int32_t special, int32_t dir, int32_t input_x, int32_t input_y, bool kb)
2742 {
2743 int32_t yg = (special==spw_floater)?8:0;
2744 int32_t nb = get_bit(quest_rules, qr_NOBORDER) ? 16 : 0;
2745 //Z_eventlog("Checking x,y %d,%d\n",dx,dy);
2746 if(input_x == -1000)
2747 input_x = dx;
2748 if(input_y == -1000)
2749 input_y = dy;
2750
2751 if(!(moveflags & FLAG_IGNORE_SCREENEDGE)
2752 && (input_x<16-nb || input_y<zc_max(16-yg-nb,0)
2753 || input_x>=240+nb-hxsz || input_y>=160+nb-hysz))
2754 return true;
2755
2756 if(!(moveflags & FLAG_CAN_PITWALK) && (!(moveflags & FLAG_CAN_PITFALL) || !kb)) //Don't walk into pits, unless being knocked back
2757 {
2758 if(ispitfall(dx,dy))
2759 return true;
2760 }
2761
2762 bool flying = false;
2763 bool cansolid = false;
2764 if(moveflags & FLAG_IGNORE_SOLIDITY)
2765 cansolid = true;
2766 switch(special)
2767 {
2768 case spw_clipbottomright:
2769 if(dy>=128 || dx>=208) return true;
2770 break;
2771 case spw_clipright:
2772 break; //if(input_x>=208) return true; break;
2773
2774 case spw_wizzrobe: // fall through
2775 case spw_floater: // Special case for fliers and wizzrobes - hack!
2776 {
2777 if(isdungeon() && !(moveflags & FLAG_IGNORE_SCREENEDGE))
2778 {
2779 if(dy < 32-yg || dy >= 144) return true;
2780 if(dx < 32 || dx >= 224) return true;
2781 }
2782 if(!(moveflags & FLAG_IGNORE_BLOCKFLAGS) && flyerblocked(dx, dy, special, kb))
2783 return true;
2784 cansolid = true;
2785 flying = true;
2786 }
2787 }
2788
2789 dx &= ~7;
2790 dy &= ~7;
2791
2792 if(!flying && !(moveflags & FLAG_IGNORE_BLOCKFLAGS) && groundblocked(dx,dy,kb)) return true;
2793
2794 if (dx < 0 || dx > 255 || dy < 0 || dy > 175)
2795 return false;
2796 //_walkflag code
2797 mapscr *s1, *s2;
2798 s1=(((*tmpscr).layermap[0]-1)>=0)?tmpscr2:NULL;
2799 s2=(((*tmpscr).layermap[1]-1)>=0)?tmpscr2+1:NULL;
2800
2801 int32_t cpos=(dx>>4)+(dy&0xF0);
2802 int32_t ci = tmpscr->data[cpos], ci1 = (s1?s1:tmpscr)->data[cpos], ci2 = (s2?s2:tmpscr)->data[cpos];
2803 newcombo const& c = combobuf[ci];
2804 newcombo const& c1 = combobuf[ci1];
2805 newcombo const& c2 = combobuf[ci2];
2806
2807 int32_t b=1;
2808 if(dx&8) b<<=2;
2809 if(dy&8) b<<=1;
2810
2811 #define iwtr(cmb, x, y, shallow) \
2812 (shallow \
2813 ? iswaterex(cmb, currmap, currscr, -1, dx, dy, false, false, false, true, false) \
2814 && !iswaterex(cmb, currmap, currscr, -1, dx, dy, false, false, false, false, false) \
2815 : iswaterex(cmb, currmap, currscr, -1, dx, dy, false, false, false, false, false))
2816 bool wtr = iwtr(ci, dx, dy, false);
2817 bool shwtr = iwtr(ci, dx, dy, true);
2818 bool pit = ispitfall(dx,dy);
2819
2820 bool canwtr = (moveflags & FLAG_CAN_WATERWALK) || ((moveflags & FLAG_CAN_WATERDROWN) && kb);
2821 bool canpit = (moveflags & FLAG_CAN_PITWALK) || ((moveflags & FLAG_CAN_PITFALL) && kb);
2822 bool needwtr = (moveflags & FLAG_ONLY_WATERWALK);
2823 bool needshwtr = (moveflags & FLAG_ONLY_SHALLOW_WATERWALK);
2824 bool needpit = (moveflags & FLAG_ONLY_PITWALK);
2825
2826 int32_t cwalkflag = c.walk & 0xF;
2827 if (c.type == cBRIDGE && get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS)) cwalkflag = 0;
2828 if (s1)
2829 {
2830 if (c1.type == cBRIDGE)
2831 {
2832 if (!get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
2833 {
2834 int efflag = (c1.walk & 0xF0)>>4;
2835 int newsolid = (c1.walk & 0xF);
2836 cwalkflag = ((newsolid | cwalkflag) & (~efflag)) | (newsolid & efflag);
2837 }
2838 else cwalkflag &= c1.walk;
2839 }
2840 else cwalkflag |= c1.walk & 0xF;
2841 }
2842 if (s2)
2843 {
2844 if (c2.type == cBRIDGE)
2845 {
2846 if (!get_bit(quest_rules, qr_OLD_BRIDGE_COMBOS))
2847 {
2848 int efflag = (c2.walk & 0xF0)>>4;
2849 int newsolid = (c2.walk & 0xF);
2850 cwalkflag = ((newsolid | cwalkflag) & (~efflag)) | (newsolid & efflag);
2851 }
2852 else cwalkflag &= c2.walk;
2853 }
2854 else cwalkflag |= c2.walk & 0xF;
2855 }
2856 bool solid = cwalkflag & b;
2857 if (solid && !cansolid) return true;
2858 if(needwtr || needshwtr || needpit)
2859 {
2860 bool ret = true;
2861 if (needwtr && wtr) ret = false;
2862 else if (needshwtr && shwtr) ret = false;
2863 else if (needpit && pit) ret = false;
2864 return ret;
2865 }
2866 else if(wtr && !canwtr)
2867 return true;
2868 else if(pit && !canpit)
2869 return true;
2870
2871 return false;
2872 }
2873
2874 bool enemy::scr_canmove(zfix dx, zfix dy, int32_t special, bool kb, bool ign_sv)
2875 {
2876 if(!(dx || dy)) return true;
2877 zfix bx = x+hxofs, by = y+hyofs; //left/top
2878 zfix rx = bx+hxsz-1, ry = by+hysz-1; //right/bottom
2879 if(!ign_sv && dy < 0) //check gravity
2880 {
2881 if((moveflags & FLAG_OBEYS_GRAV) && isSideViewGravity())
2882 return false;
2883 }
2884
2885 if(dx && !dy)
2886 {
2887 if(dx < 0)
2888 {
2889 special = (special==spw_clipbottomright||special==spw_clipright)?spw_none:special;
2890 int32_t tx = (bx+dx).getFloor();
2891 for(zfix ty = 0; by+ty < ry; ty += 8)
2892 {
2893 if(scr_walkflag(tx, by+ty, special, left, bx, by, kb))
2894 return false;
2895 }
2896 if(scr_walkflag(tx, ry, special, left, bx, by, kb))
2897 return false;
2898 }
2899 else
2900 {
2901 int32_t tx = (rx+dx).getCeil();
2902 for(zfix ty = 0; by+ty < ry; ty += 8)
2903 {
2904 if(scr_walkflag(tx, by+ty, special, right, bx, by, kb))
2905 return false;
2906 }
2907 if(scr_walkflag(tx, ry, special, right, bx, by, kb))
2908 return false;
2909 }
2910 }
2911 else if(dy && !dx)
2912 {
2913 if(dy < 0)
2914 {
2915 special = (special==spw_clipbottomright)?spw_none:special;
2916 int32_t ty = (by+dy).getFloor();
2917 for(zfix tx = 0; bx+tx < rx; tx += 8)
2918 {
2919 if(scr_walkflag(bx+tx, ty, special, up, bx, by, kb))
2920 return false;
2921 }
2922 if(scr_walkflag(rx, ty, special, up, bx, by, kb))
2923 return false;
2924 }
2925 else
2926 {
2927 int32_t ty = (ry+dy).getCeil();
2928 for(zfix tx = 0; bx+tx < rx; tx += 8)
2929 {
2930 if(scr_walkflag(bx+tx, ty, special, down, bx, by, kb))
2931 return false;
2932 }
2933 if(scr_walkflag(rx, ty, special, down, bx, by, kb))
2934 return false;
2935 }
2936 }
2937 else
2938 {
2939 return scr_canmove(dx, 0, special, kb, ign_sv) && scr_canmove(dy, 0, special, kb, ign_sv);
2940 }
2941 return true;
2942 }
2943
2944 bool enemy::scr_canplace(zfix dx, zfix dy, int32_t special, bool kb)
2945 {
2946 zfix bx = dx+hxofs, by = dy+hyofs; //left/top
2947 zfix rx = bx+hxsz-1, ry = by+hysz-1; //right/bottom
2948
2949 for(zfix ty = 0; by+ty < ry; ty += 8)
2950 {
2951 for(zfix tx = 0; bx+tx < rx; tx += 8)
2952 {
2953 if(scr_walkflag(bx+tx, by+ty, special, -1, -1000, -1000, kb))
2954 return false;
2955 }
2956 if(scr_walkflag(rx, by+ty, special, -1, -1000, -1000, kb))
2957 return false;
2958 }
2959 for(zfix tx = 0; bx+tx < rx; tx += 8)
2960 {
2961 if(scr_walkflag(bx+tx, ry, special, -1, -1000, -1000, kb))
2962 return false;
2963 }
2964 if(scr_walkflag(rx, ry, special, -1, -1000, -1000, kb))
2965 return false;
2966 return true;
2967 }
2968
2969 bool enemy::movexy(zfix dx, zfix dy, int32_t special, bool kb, bool ign_sv)
2970 {
2971 bool ret = true;
2972 if(!ign_sv && dy < 0 && (moveflags & FLAG_OBEYS_GRAV) && isSideViewGravity())
2973 dy = 0;
2974 while(abs(dx) > 8 || abs(dy) > 8)
2975 {
2976 if(abs(dx) > abs(dy))
2977 {
2978 int32_t tdx = dx.sign() * 8;
2979 if(movexy(tdx, 0, special, kb, ign_sv))
2980 dx -= tdx;
2981 else
2982 {
2983 dx = tdx;
2984 ret = false;
2985 }
2986 }
2987 else
2988 {
2989 int32_t tdy = dy.sign() * 8;
2990 if(movexy(0, tdy, special, kb, ign_sv))
2991 dy -= tdy;
2992 else
2993 {
2994 dy = tdy;
2995 ret = false;
2996 }
2997 }
2998 }
2999 if(dx)
3000 {
3001 if(scr_canmove(dx, 0, special, kb, ign_sv))
3002 x += dx;
3003 else
3004 {
3005 ret = false;
3006 int32_t xsign = dx.sign();
3007 while(scr_canmove(xsign, 0, special, kb, ign_sv))
3008 {
3009 x += xsign;
3010 dx -= xsign;
3011 }
3012 if(scr_canmove(dx.decsign(), 0, special, kb, ign_sv)) //can move 0.0001 to 0.9999 px in this direction
3013 {
3014 if(dx > 0)
3015 x.doCeil();
3016 else x.doFloor();
3017 }
3018 }
3019 }
3020 if(dy)
3021 {
3022 if(scr_canmove(0, dy, special, kb, ign_sv))
3023 y += dy;
3024 else
3025 {
3026 ret = false;
3027 int32_t ysign = dy.sign();
3028 while(scr_canmove(0, ysign, special, kb, ign_sv))
3029 {
3030 y += ysign;
3031 dy -= ysign;
3032 }
3033 if(scr_canmove(0, dy.decsign(), special, kb, ign_sv)) //can move 0.0001 to 0.9999 px in this direction
3034 {
3035 if(dy > 0)
3036 y.doCeil();
3037 else y.doFloor();
3038 }
3039 }
3040 }
3041 return ret;
3042 }
3043
3044 bool enemy::moveDir(int32_t dir, zfix px, int32_t special, bool kb)
3045 {
3046 zfix diagrate = zslongToFix(7071);
3047 switch(NORMAL_DIR(dir))
3048 {
3049 case up:
3050 return movexy(0, -px, special, kb);
3051 case down:
3052 return movexy(0, px, special, kb);
3053 case left:
3054 return movexy(-px, 0, special, kb);
3055 case right:
3056 return movexy(px, 0, special, kb);
3057 case r_up:
3058 return movexy(px*diagrate, -px*diagrate, special, kb);
3059 case r_down:
3060 return movexy(px*diagrate, px*diagrate, special, kb);
3061 case l_up:
3062 return movexy(-px*diagrate, -px*diagrate, special, kb);
3063 case l_down:
3064 return movexy(-px*diagrate, px*diagrate, special, kb);
3065 }
3066 return false;
3067 }
3068
3069 bool enemy::moveAtAngle(zfix degrees, zfix px, int32_t special, bool kb)
3070 {
3071 double v = degrees.getFloat() * PI / 180.0;
3072 zfix dx = zc::math::Cos(v)*px, dy = zc::math::Sin(v)*px;
3073 return movexy(dx, dy, special, kb);
3074 }
3075
3076 bool enemy::can_movexy(zfix dx, zfix dy, int32_t special, bool kb)
3077 {
3078 zfix tx = x, ty = y;
3079 bool ret = movexy(dx, dy, special, kb);
3080 x = tx;
3081 y = ty;
3082 return ret;
3083 }
3084 bool enemy::can_moveDir(int32_t dir, zfix px, int32_t special, bool kb)
3085 {
3086 zfix tx = x, ty = y;
3087 bool ret = moveDir(dir, px, special, kb);
3088 x = tx;
3089 y = ty;
3090 return ret;
3091 }
3092 bool enemy::can_moveAtAngle(zfix degrees, zfix px, int32_t special, bool kb)
3093 {
3094 zfix tx = x, ty = y;
3095 bool ret = moveAtAngle(degrees, px, special, kb);
3096 x = tx;
3097 y = ty;
3098 return ret;
3099 }
3100
3101 // Handle pitfalls
3102 3650 bool enemy::do_falling(int32_t index)
3103 {
3104
1/2
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
3650 if(fallclk > 0)
3105 {
3106 if(fallclk == PITFALL_FALL_FRAMES && fallCombo) sfx(combobuf[fallCombo].attribytes[0], pan(x.getInt()));
3107 if(!--fallclk)
3108 {
3109 if(immortal) //Keep alive forever
3110 ++fallclk; //force another frame of falling.... forever.
3111 else if(dying) //Give 1 frame for script revival
3112 {
3113 if(flags&guy_neverret)
3114 never_return(index);
3115
3116 if(leader)
3117 kill_em_all();
3118
3119 //leave_item(); //Don't drop items in pits!
3120 stop_bgsfx(index);
3121 return true;
3122 }
3123 else
3124 {
3125 try_death(true); //Force death
3126 ++fallclk; //force another frame of falling
3127 }
3128 }
3129
3130 wpndata& spr = wpnsbuf[QMisc.sprites[sprFALL]];
3131 cs = spr.csets & 0xF;
3132 int32_t fr = spr.frames ? spr.frames : 1;
3133 int32_t spd = spr.speed ? spr.speed : 1;
3134 int32_t animclk = (PITFALL_FALL_FRAMES-fallclk);
3135 tile = spr.tile + zc_min(animclk / spd, fr-1);
3136 }
3137 3650 return false;
3138 3650 }
3139
3140 // Handle drowning in water
3141 3650 bool enemy::do_drowning(int32_t index)
3142 {
3143
1/2
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
3650 if(drownclk > 0)
3144 {
3145 //if(drownclk == WATER_DROWN_FRAMES && drownCombo) sfx(combobuf[drownCombo].attribytes[0], pan(x.getInt()));
3146 //!TODO: Drown SFX
3147 if(!--drownclk)
3148 {
3149 if(immortal) //Keep alive forever
3150 ++drownclk; //force another frame of falling.... forever.
3151 else if(dying) //Give 1 frame for script revival
3152 {
3153 if(flags&guy_neverret)
3154 never_return(index);
3155
3156 if(leader)
3157 kill_em_all();
3158
3159 //leave_item(); //Don't drop items in pits!
3160 stop_bgsfx(index);
3161 return true;
3162 }
3163 else
3164 {
3165 try_death(true); //Force death
3166 ++drownclk; //force another frame of falling
3167 }
3168 }
3169
3170 if (drownCombo && combobuf[drownCombo].usrflags&cflag1)
3171 {
3172 wpndata &spr = wpnsbuf[QMisc.sprites[sprLAVADROWN]];
3173 cs = spr.csets & 0xF;
3174 int32_t fr = spr.frames ? spr.frames : 1;
3175 int32_t spd = spr.speed ? spr.speed : 1;
3176 int32_t animclk = (WATER_DROWN_FRAMES-drownclk);
3177 tile = spr.tile + zc_min((animclk % (spd*fr))/spd, fr-1);
3178 }
3179 else
3180 {
3181 wpndata &spr = wpnsbuf[QMisc.sprites[sprDROWN]];
3182 cs = spr.csets & 0xF;
3183 int32_t fr = spr.frames ? spr.frames : 1;
3184 int32_t spd = spr.speed ? spr.speed : 1;
3185 int32_t animclk = (WATER_DROWN_FRAMES-drownclk);
3186 tile = spr.tile + zc_min((animclk % (spd*fr))/spd, fr-1);
3187 }
3188 }
3189 3650 return false;
3190 3650 }
3191
3192 // Supplemental animation code that all derived classes should call
3193 // as a return value for animate().
3194 // Handles the death animation and returns true when enemy is finished.
3195 3776 bool enemy::Dead(int32_t index)
3196 {
3197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3776 times.
3776 if(immortal)
3198 {
3199 dying = false;
3200 return false;
3201 }
3202
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 3643 times.
3776 if(dying)
3203 {
3204
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
133 if(deathexstate > -1 && deathexstate < 32)
3205 {
3206 setxmapflag(1<<deathexstate);
3207 deathexstate = -1;
3208 }
3209 133 --clk2;
3210
3211
2/4
✓ Branch 0 taken 133 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
133 if((get_bit(quest_rules,qr_HARDCODED_ENEMY_ANIMS) && clk2==12)
3212
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 126 times.
133 && hp>-1000) // not killed by ringleader
3213 7 death_sfx();
3214
3215
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 7 times.
133 if(clk2==0)
3216 {
3217
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(flags&guy_neverret)
3218 never_return(index);
3219
3220
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(leader)
3221 kill_em_all();
3222
3223 7 leave_item();
3224 7 }
3225
3226 133 stop_bgsfx(index);
3227 133 return (clk2==0);
3228 }
3229
3230 3643 return false;
3231 3776 }
3232
3233 // Basic animation code that all derived classes should call.
3234 // The one with an index is the one that is called by
3235 // the guys sprite list; index is the enemy's index in the list.
3236 4236 bool enemy::animate(int32_t index)
3237 {
3238
2/2
✓ Branch 0 taken 590 times.
✓ Branch 1 taken 3646 times.
4236 if(sclk <= 0) hitdir = -1;
3239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4236 times.
4236 if(switch_hooked)
3240 {
3241 if(get_bit(quest_rules, qr_SWITCHOBJ_RUN_SCRIPT))
3242 {
3243 //Run its script
3244 if (run_script(MODE_NORMAL)==RUNSCRIPT_SELFDELETE)
3245 {
3246 return 0; //Avoid NULLPO if this object deleted itself
3247 }
3248 }
3249 return false;
3250 }
3251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4236 times.
4236 if(do_falling(index)) return true;
3252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4236 times.
4236 else if(fallclk)
3253 {
3254 //clks
3255 if(hclk>0)
3256 --hclk;
3257 if(stunclk>0)
3258 --stunclk;
3259 if ( frozenclock > 0 )
3260 --frozenclock;
3261 if(hashero)
3262 {
3263 Hero.setX(x);
3264 Hero.setY(y);
3265 Hero.fallCombo = fallCombo;
3266 Hero.fallclk = fallclk;
3267 hashero = false; //Let Hero go if falling
3268 }
3269 run_script(MODE_NORMAL);
3270 return false;
3271 }
3272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4236 times.
4236 if(do_drowning(index)) return true;
3273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4236 times.
4236 else if(drownclk)
3274 {
3275 //clks
3276 if(hclk>0)
3277 --hclk;
3278 if(stunclk>0)
3279 --stunclk;
3280 if ( frozenclock > 0 )
3281 --frozenclock;
3282 if(hashero)
3283 {
3284 Hero.setX(x);
3285 Hero.setY(y);
3286 Hero.drownclk = drownclk;
3287 hashero = false; //Let Hero go if falling
3288 }
3289 run_script(MODE_NORMAL);
3290 return false;
3291 }
3292 4236 int32_t nx = real_x(x);
3293 4236 int32_t ny = real_y(y);
3294
3295
4/4
✓ Branch 0 taken 2955 times.
✓ Branch 1 taken 1281 times.
✓ Branch 2 taken 2062 times.
✓ Branch 3 taken 5017 times.
4236 if(ox!=nx || oy!=ny)
3296 {
3297 3343 posframe=(posframe+1)%(get_bit(quest_rules,qr_NEWENEMYTILES)?4:2);
3298 3343 }
3299
3300 5798 ox = nx;
3301 5798 oy = ny;
3302
3303 // Maybe they fell off the bottom in sideview, or were moved by a script.
3304
3305 //Check offscreen settings. I wrote it this way for clarity and to simplify testing. -Z
3306
2/2
✓ Branch 0 taken 2148 times.
✓ Branch 1 taken 3650 times.
5798 if ( immortal )
3307 {
3308 //skip, as it can go out of bounds, from immortality
3309 2148 }
3310
2/6
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3650 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3650 else if ( (moveflags & FLAG_IGNORE_SCREENEDGE) || (( (get_bit(quest_rules, qr_OUTOFBOUNDSENEMIES)) != (editorflags&ENEMY_FLAG11) ) && !NEWOUTOFBOUNDS(x,y,z+fakez)) )
3311 {
3312 //skip, it can go out of bounds, from a quest rule, or from the enemy editor (but not both!)
3313 }
3314
5/10
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3650 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3650 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3650 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3650 times.
3650 else if ( (OUTOFBOUNDS) )
3315 {
3316 hp=-1000; //kill it, as it is not immortal, and no quest bit or rule is enabled
3317 }
3318 //fall down
3319
6/6
✓ Branch 0 taken 2362 times.
✓ Branch 1 taken 3436 times.
✓ Branch 2 taken 1288 times.
✓ Branch 3 taken 4510 times.
✓ Branch 4 taken 150 times.
✓ Branch 5 taken 1138 times.
5798 if((enemycanfall(id) || (moveflags & FLAG_OBEYS_GRAV) )&& fading != fade_flicker && clk>=0)
3320 {
3321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1138 times.
1138 if(isSideViewGravity())
3322 {
3323 if(get_bit(quest_rules,qr_OLD_SIDEVIEW_LANDING_CODE))
3324 {
3325 if(!isOnSideviewPlatform())
3326 {
3327 bool willHitSVPlatform = false;
3328 int32_t usewid = (SIZEflags&guyflagOVERRIDE_HIT_WIDTH)?hxsz:16;
3329 int32_t usehei = (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT)?hysz:16;
3330 for(int32_t nx = x+4; nx < x+usewid; nx+=16)
3331 {
3332 if(fall > 0 && !IGNORE_SIDEVIEW_PLATFORMS && checkSVLadderPlatform(x+4,y+(fall/100)+usehei-1) && (((int32_t(y)+(int32_t(fall)/100)+usehei-1)&0xF0)!=((int32_t(y)+usehei-1)&0xF0)))
3333 {
3334 willHitSVPlatform = true;
3335 break;
3336 }
3337 }
3338 if(willHitSVPlatform)
3339 {
3340 y+=fall/100;
3341 //y-=int32_t(y)%16; //Fix to top of SV Ladder
3342 do_fix(y, 16); //Fix to top of SV Ladder
3343 fall = 0;
3344 }
3345 else
3346 {
3347 y+=fall/100;
3348 if(fall <= (int32_t)zinit.terminalv)
3349 fall += (zinit.gravity2/100);
3350 }
3351 }
3352 else
3353 {
3354 if(fall!=0) // Only fix pos once
3355 {
3356 //y-=(int32_t)y%8; // Fix position
3357 do_fix(y, 8); //Fix position
3358 }
3359
3360 fall = 0;
3361 }
3362 }
3363 else
3364 {
3365 if(isOnSideviewPlatform())
3366 fall = 0;
3367 else
3368 {
3369 zfix fall_amnt = fall/100;
3370 bool hit = false;
3371 while(fall_amnt >= 1)
3372 {
3373 --fall_amnt;
3374 ++y;
3375 if(isOnSideviewPlatform())
3376 {
3377 y = y.getInt();
3378 fall_amnt = 0;
3379 hit = true;
3380 break;
3381 }
3382 }
3383 if(fall_amnt > 0)
3384 y += fall_amnt;
3385 if(fall_amnt < 0)
3386 {
3387 if(!movexy(0,fall_amnt,spw_none))
3388 hit = true;
3389 }
3390 if(hit)
3391 fall = 0;
3392 else if(fall <= (int32_t)zinit.terminalv)
3393 fall += (zinit.gravity2/100);
3394 }
3395 }
3396 }
3397 else
3398 {
3399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1138 times.
1138 if (!(moveflags & FLAG_NO_FAKE_Z))
3400 {
3401
2/2
✓ Branch 0 taken 570 times.
✓ Branch 1 taken 568 times.
1138 if(fakefall!=0)
3402 568 fakez-=(fakefall/100);
3403
3404
2/2
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 570 times.
1138 if(fakez<0)
3405 568 fakez = fakefall = 0;
3406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
570 else if(fakefall <= (int32_t)zinit.terminalv)
3407 570 fakefall += (zinit.gravity2/100);
3408
3409
4/6
✓ Branch 0 taken 1138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 570 times.
✓ Branch 3 taken 568 times.
✓ Branch 4 taken 570 times.
✗ Branch 5 not taken.
1138 if (fakez<=0 && fakefall > 0 && !get_bit(quest_rules, qr_FLUCTUATING_ENEMY_JUMP)) fakefall = 0;
3410 1138 }
3411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1138 times.
1138 if (!(moveflags & FLAG_NO_REAL_Z))
3412 {
3413
2/2
✓ Branch 0 taken 570 times.
✓ Branch 1 taken 568 times.
1138 if(fall!=0)
3414 568 z-=(fall/100);
3415
3416
2/2
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 570 times.
1138 if(z<0)
3417 568 z = fall = 0;
3418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
570 else if(fall <= (int32_t)zinit.terminalv)
3419 570 fall += (zinit.gravity2/100);
3420
3421
4/6
✓ Branch 0 taken 1138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 570 times.
✓ Branch 3 taken 568 times.
✓ Branch 4 taken 570 times.
✗ Branch 5 not taken.
1138 if (z<=0 && fall > 0 && !get_bit(quest_rules, qr_FLUCTUATING_ENEMY_JUMP)) fall = 0;
3422 1138 }
3423
3424 }
3425 1138 }
3426
4/4
✓ Branch 0 taken 3650 times.
✓ Branch 1 taken 2148 times.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 3864 times.
5798 if(!isSideViewGravity() && (moveflags & FLAG_CAN_PITFALL))
3427 {
3428
7/10
✓ Branch 0 taken 1288 times.
✓ Branch 1 taken 2576 times.
✓ Branch 2 taken 1288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1288 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1288 times.
✓ Branch 8 taken 1288 times.
✓ Branch 9 taken 1288 times.
3864 if(can_pitfall() && ((z <= 0 && fakez <= 0 && !isflier(id)) || (isflier(id) && (stunclk))) && !superman)
3429 {
3430 1288 fallCombo = check_pits();
3431 1288 }
3432 6440 }
3433
2/4
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3650 times.
✗ Branch 3 not taken.
3650 if(!isSideViewGravity() && (moveflags & FLAG_CAN_WATERDROWN))
3434 {
3435 if(can_pitfall() && ((z <= 0 && fakez <= 0 && !isflier(id)) || (isflier(id) && (stunclk))) && !superman)
3436 {
3437 drownCombo = check_water();
3438 }
3439 }
3440
3441 3650 runKnockback(); //scripted knockback handling
3442
3443 // clk is incremented here
3444
2/2
✓ Branch 0 taken 3498 times.
✓ Branch 1 taken 152 times.
3650 if(++clk >= frate)
3445 152 clk=0;
3446
3447 // hit and death handling
3448
2/2
✓ Branch 0 taken 3643 times.
✓ Branch 1 taken 7 times.
3650 if(hclk>0)
3449 7 --hclk;
3450
3451
1/2
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
3650 if(stunclk>0)
3452 --stunclk;
3453
1/2
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
3650 if ( frozenclock > 0 )
3454 --frozenclock;
3455
3456
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3650 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3650 if(ceiling && z <= 0 && fakez <= 0)
3457 ceiling = false;
3458
3459 3650 try_death();
3460
3461 3650 scored=false;
3462
3463 3650 ++c_clk;
3464
3465 //Run its script
3466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3650 times.
3650 if (run_script(MODE_NORMAL)==RUNSCRIPT_SELFDELETE)
3467 {
3468 return 0; //Avoid NULLPO if this object deleted itself
3469 }
3470
3471 // returns true when enemy is defeated
3472 3650 return Dead(index);
3473 3650 }
3474
3475 3769 bool enemy::setSolid(bool set)
3476 {
3477
1/2
✓ Branch 0 taken 3769 times.
✗ Branch 1 not taken.
3769 bool actual = set && !isSubmerged();
3478 3769 bool ret = solid_object::setSolid(actual);
3479 3769 solid = set;
3480 3769 return ret;
3481 }
3482 void enemy::doContactDamage(int32_t hdir)
3483 {
3484 Hero.hithero(guys.find(this), hdir);
3485 }
3486
3487 void enemy::solid_push(solid_object *obj)
3488 {
3489 if(obj == this) return; //can't push self
3490 if(moveflags&FLAG_NOT_PUSHABLE) return; //not pushable
3491 zfix dx, dy;
3492 int32_t hdir = -1;
3493 solid_push_int(obj,dx,dy,hdir);
3494
3495 if(!dx && !dy) return;
3496
3497 bool t = obj->getTempNonsolid();
3498 obj->setTempNonsolid(true);
3499
3500 int32_t ydir = dy > 0 ? down : up;
3501 int32_t xdir = dx > 0 ? right : left;
3502
3503 auto special = isflier(id) ? spw_floater : spw_none;
3504 if(!movexy(dx,dy,special,true,true))
3505 {
3506 //Crushed?
3507 }
3508
3509 obj->setTempNonsolid(t);
3510 }
3511 bool enemy::is_unpushable() const
3512 {
3513 return isSubmerged();
3514 }
3515 bool enemy::sideview_mode() const
3516 {
3517 return isSideViewGravity() && (moveflags&FLAG_OBEYS_GRAV) && !(moveflags&FLAG_NOT_PUSHABLE);
3518 }
3519
3520 bool enemy::m_walkflag_old(int32_t dx,int32_t dy,int32_t special, int32_t x, int32_t y)
3521 {
3522 int32_t yg = (special==spw_floater)?8:0;
3523 int32_t nb = get_bit(quest_rules, qr_NOBORDER) ? 16 : 0;
3524
3525 if(dx<16-nb || dy<zc_max(16-yg-nb,0) || dx>=240+nb || dy>=160+nb)
3526 return true;
3527
3528 bool isInDungeon = isdungeon();
3529 if(isInDungeon || special==spw_wizzrobe)
3530 {
3531 if((x>=32 && dy<32-yg) || (y>-1000 && y<=144 && dy>=144))
3532 return true;
3533
3534 if((x>=32 && dx<32) || (x>-1000 && x<224 && dx>=224))
3535 if(special!=spw_door) // walk in door way
3536 return true;
3537 }
3538
3539 if(!(moveflags & FLAG_CAN_PITWALK) && !(moveflags & FLAG_CAN_PITFALL)) //Don't walk into pits (knockback doesn't call this func)
3540 {
3541 if(ispitfall(dx,dy) || ispitfall(dx+8,dy)
3542 || ispitfall(dx,dy+8) || ispitfall(dx+8,dy+8))
3543 return true;
3544 }
3545
3546 switch(special)
3547 {
3548 case spw_clipbottomright:
3549 if(dy>=128 || dx>=208) return true;
3550 break;
3551 case spw_clipright:
3552 break; //if(x>=208) return true; break;
3553
3554 case spw_wizzrobe: // fall through
3555 case spw_floater: // Special case for fliers and wizzrobes - hack!
3556 {
3557 if(isInDungeon)
3558 {
3559 if(dy < 32-yg || dy >= 144) return true;
3560 if(dx < 32 || dx >= 224) return true;
3561 }
3562 return false;
3563 }
3564 }
3565
3566 dx&=(special==spw_halfstep)?(~7):(~15);
3567 dy&=(special==spw_halfstep || isSideViewGravity())?(~7):(~15);
3568
3569 if(special==spw_water)
3570 return (water_walkflag(dx,dy+8,1) || water_walkflag(dx+8,dy+8,1));
3571
3572 return _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) ||
3573 groundblocked(dx,dy+8) || groundblocked(dx+8,dy+8);
3574 }
3575
3576 bool enemy::m_walkflag_simple(int32_t dx,int32_t dy)
3577 {
3578 bool kb = false;
3579 int32_t nb = get_bit(quest_rules, qr_NOBORDER) ? 16 : 0;
3580
3581 if(dx<16-nb || dy<zc_max(16-nb,0) || dx>=240+nb || dy>=160+nb)
3582 return true;
3583
3584 if(isdungeon())
3585 {
3586 if((dy<32) || (dy>=144))
3587 return true;
3588
3589 if((dx<32) || (dx>=224))
3590 return true;
3591 }
3592
3593 if(!(moveflags & FLAG_CAN_PITWALK) && (!(moveflags & FLAG_CAN_PITFALL))) //Don't walk into pits, unless being knocked back
3594 {
3595 if(ispitfall(dx,dy) || ispitfall(dx+8,dy)
3596 || ispitfall(dx,dy+8) || ispitfall(dx+8,dy+8))
3597 return true;
3598 }
3599
3600 if(get_bit(quest_rules,qr_ENEMY_BROKEN_TOP_HALF_SOLIDITY))
3601 {
3602 return _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) ||
3603 groundblocked(dx,dy+8,kb) || groundblocked(dx+8,dy+8,kb);
3604 }
3605 else
3606 {
3607 return _walkflag(dx,dy,1) || _walkflag(dx+8,dy,1) ||
3608 _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) ||
3609 groundblocked(dx,dy,kb) || groundblocked(dx+8,dy,kb) ||
3610 groundblocked(dx,dy+8,kb) || groundblocked(dx+8,dy+8,kb);
3611 }
3612 }
3613
3614 54 bool enemy::m_walkflag(int32_t dx,int32_t dy,int32_t special, int32_t dir, int32_t input_x, int32_t input_y, bool kb)
3615 {
3616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if(moveflags & FLAG_USE_NEW_MOVEMENT)
3617 return scr_walkflag(dx,dy,special,dir,input_x,input_y,kb);
3618 54 int32_t yg = (special==spw_floater)?8:0;
3619 54 int32_t nb = get_bit(quest_rules, qr_NOBORDER) ? 16 : 0;
3620
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 42 times.
54 switch(dir)
3621 {
3622 case l_down:
3623 case r_down:
3624 case down:
3625 case 11: //r_down
3626 case 12: //down
3627 case 13: //l_down
3628 {
3629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ( ((unsigned)(id&0xFFF)) < MAXGUYS )
3630 {
3631
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 if ( SIZEflags&guyflagOVERRIDE_HIT_HEIGHT && !isflier(id) )
3632 {
3633 //Small enemies are treated as 16x16, for the purposes of m_walkflag!
3634 dy += zc_max(hysz-16,0);
3635 }
3636 12 }
3637 12 break;
3638 }
3639 }
3640
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
54 switch(dir)
3641 {
3642 case r_up:
3643 case r_down:
3644 case right:
3645 case 9: //r_up
3646 case 10: //right
3647 case 11: //r_down
3648 {
3649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if ( ((unsigned)(id&0xFFF)) < MAXGUYS )
3650 {
3651
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if ( SIZEflags&guyflagOVERRIDE_HIT_WIDTH && !isflier(id) )
3652 {
3653 //Small enemies are treated as 16x16, for the purposes of m_walkflag!
3654 dx += zc_max(hxsz-16,0);
3655 }
3656 7 }
3657 7 break;
3658 }
3659 }
3660 //Z_eventlog("Checking x,y %d,%d\n",dx,dy);
3661
3662
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 49 times.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 49 times.
54 if(dx<16-nb || dy<zc_max(16-yg-nb,0) || dx>=240+nb || dy>=160+nb)
3663 5 return true;
3664
3665 49 bool isInDungeon = isdungeon();
3666
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
49 if(isInDungeon || special==spw_wizzrobe)
3667 {
3668 if((input_x>=32 && dy<32-yg) || (input_y>-1000 && input_y<=144 && dy>=144))
3669 return true;
3670
3671 if((input_x>=32 && dx<32) || (input_x>-1000 && input_x<224 && dx>=224))
3672 if(special!=spw_door) // walk in door way
3673 return true;
3674 }
3675
3676
3/6
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 49 times.
49 if(!(moveflags & FLAG_CAN_PITWALK) && (!(moveflags & FLAG_CAN_PITFALL) || !kb)) //Don't walk into pits, unless being knocked back
3677 {
3678
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
98 if(ispitfall(dx,dy) || ispitfall(dx+8,dy)
3679
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 || ispitfall(dx,dy+8) || ispitfall(dx+8,dy+8))
3680 return true;
3681 49 }
3682
3683
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
49 switch(special)
3684 {
3685 case spw_clipbottomright:
3686 if(dy>=128 || dx>=208) return true;
3687 break;
3688 case spw_clipright:
3689 break; //if(input_x>=208) return true; break;
3690
3691 case spw_wizzrobe: // fall through
3692 case spw_floater: // Special case for fliers and wizzrobes - hack!
3693 {
3694 if(isInDungeon)
3695 {
3696 if(dy < 32-yg || dy >= 144) return true;
3697 if(dx < 32 || dx >= 224) return true;
3698 }
3699 return false;
3700 }
3701 }
3702
3703 49 dx&=(special==spw_halfstep)?(~7):(~15);
3704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 dy&=(special==spw_halfstep || isSideViewGravity())?(~7):(~15);
3705
3706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if(special==spw_water)
3707 return (water_walkflag(dx,dy+8,1) || water_walkflag(dx+8,dy+8,1));
3708
3709
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if(get_bit(quest_rules,qr_ENEMY_BROKEN_TOP_HALF_SOLIDITY))
3710 {
3711
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
77 return _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) ||
3712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 groundblocked(dx,dy+8,kb) || groundblocked(dx+8,dy+8,kb);
3713 }
3714 else
3715 {
3716 return _walkflag(dx,dy,1) || _walkflag(dx+8,dy,1) ||
3717 _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) ||
3718 groundblocked(dx,dy,kb) || groundblocked(dx+8,dy,kb) ||
3719 groundblocked(dx,dy+8,kb) || groundblocked(dx+8,dy+8,kb);
3720 }
3721 54 }
3722
3723 bool enemy::isOnSideviewPlatform()
3724 {
3725 int32_t usewid = (SIZEflags&guyflagOVERRIDE_HIT_WIDTH) ? hxsz : 16;
3726 int32_t usehei = (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) ? hysz : 16;
3727 if(y + usehei >= 176 && currscr>=0x70 && !(tmpscr->flags2&wfDOWN)) return true; //Bottom of the map
3728 if(check_slope(x, y+1, usewid, usehei)) return true;
3729 for(int32_t nx = x + 4; nx <= x + usewid - 4; nx+=16)
3730 {
3731 if(_walkflag(nx,y+usehei,1)) return true;
3732 if(IGNORE_SIDEVIEW_PLATFORMS || ((int32_t(y)+usehei)%16)!=0) continue;
3733 if(checkSVLadderPlatform(nx,y+usehei)) return true;
3734 }
3735 return false;
3736 }
3737
3738 // Stops playing the given sound only if there are no enemies left to play it
3739 133 void enemy::stop_bgsfx(int32_t index)
3740 {
3741
1/2
✓ Branch 0 taken 133 times.
✗ Branch 1 not taken.
133 if(bgsfx<=0)
3742 133 return;
3743
3744 // Look for other enemies with the same bgsfx
3745 for(int32_t i=0; i<guys.Count(); i++)
3746 {
3747 if(i!=index && ((enemy*)guys.spr(i))->bgsfx==bgsfx)
3748 return;
3749 }
3750
3751 stop_sfx(bgsfx);
3752 133 }
3753
3754
3755 // to allow for different sfx on defeating enemy
3756 7 void enemy::death_sfx()
3757 {
3758
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(deadsfx > 0) sfx(deadsfx,pan(int32_t(x)));
3759 7 }
3760
3761 void enemy::move(zfix dx,zfix dy)
3762 {
3763 /*if(FFCore.getQuestHeaderInfo(vZelda) >= 0x255 && FFCore.getQuestHeaderInfo(vBuild) >= 50 )
3764 {
3765 switch(family)
3766 {
3767 case eeFIRE:
3768 case eeOTHER:
3769 return;
3770 default: break;
3771 }
3772 if(family >= eeSCRIPT01 && family <= eeFFRIENDLY10 ) return;
3773 }
3774 */
3775 if(!watch && (!(isSideViewGravity()) || isOnSideviewPlatform() || !(moveflags & FLAG_OBEYS_GRAV) || !enemycanfall(id)))
3776 {
3777 x+=dx;
3778 y+=dy;
3779 }
3780 }
3781
3782 1123 void enemy::move(zfix s)
3783 {
3784 /*if(FFCore.getQuestHeaderInfo(vZelda) >= 0x255 && FFCore.getQuestHeaderInfo(vBuild) >= 50 )
3785 {
3786 switch(family)
3787 {
3788 case eeFIRE:
3789 case eeOTHER:
3790 return;
3791 default: break;
3792 }
3793 if(family >= eeSCRIPT01 && family <= eeFFRIENDLY10 ) return;
3794 }*/
3795
2/10
✓ Branch 0 taken 1123 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1123 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1123 if(!watch && (!(isSideViewGravity()) || isOnSideviewPlatform() || !enemycanfall(id) || !(moveflags & FLAG_OBEYS_GRAV)))
3796 {
3797 1123 sprite::move(s);
3798 1123 }
3799 1123 }
3800
3801 7 void enemy::leave_item()
3802 {
3803 7 int32_t drop_item = select_dropitem(item_set, x, y);
3804 7 int32_t thedropset = item_set;
3805
3806 7 std::vector<int32_t> &ev = FFCore.eventData;
3807 7 ev.clear();
3808 7 ev.push_back(getUID());
3809 7 ev.push_back(drop_item*10000);
3810 7 ev.push_back(thedropset*10000);
3811
3812 7 throwGenScriptEvent(GENSCR_EVENT_ENEMY_DROP_ITEM_1);
3813 7 drop_item = vbound(ev[1] / 10000,-2,255);
3814 7 thedropset = ev[2] / 10000;
3815 7 ev.clear();
3816
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(drop_item == -2)
3817 {
3818 drop_item = select_dropitem(thedropset,x,y);
3819 }
3820
3821
3/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 if(drop_item>=0&&((itemsbuf[drop_item].family!=itype_fairy)||!m_walkflag(x,y,0,dir)))
3822 {
3823 item* itm;
3824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (get_bit(quest_rules, qr_ENEMY_DROPS_USE_HITOFFSETS))
3825 {
3826 itm = (new item(x+hxofs+(hxsz/2)-8,y+hyofs+(hysz/2)-8,(zfix)0,drop_item,ipBIGRANGE+ipTIMER,0));
3827 }
3828 else
3829 {
3830
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3 if(extend >= 3) itm = (new item(x+(txsz-1)*8,y+(tysz-1)*8,(zfix)0,drop_item,ipBIGRANGE+ipTIMER,0));
3831
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
3 else itm = (new item(x,y,(zfix)0,drop_item,ipBIGRANGE+ipTIMER,0));
3832 }
3833 3 itm->from_dropset = thedropset;
3834 3 items.add(itm);
3835
3836 3 ev.push_back(getUID());
3837 3 ev.push_back(itm->getUID());
3838
3839 3 throwGenScriptEvent(GENSCR_EVENT_ENEMY_DROP_ITEM_2);
3840 3 ev.clear();
3841 3 }
3842 7 }
3843
3844 // auomatically kill off enemy (for rooms with ringleaders)
3845 void enemy::kickbucket()
3846 {
3847 if(!superman)
3848 hp=-1000; // don't call death_sfx()
3849 }
3850
3851 bool enemy::isSubmerged() const
3852 {
3853 return submerged;
3854 //!TODO SOLIDPUSH more things like teleporting wizzrobes
3855 }
3856
3857 void enemy::FireBreath(bool seekhero)
3858 {
3859 if(wpn==wNone)
3860 return;
3861
3862 if(wpn==ewFireTrail)
3863 {
3864 dmisc1 = e1tEACHTILE;
3865 FireWeapon();
3866 return;
3867 }
3868
3869 float fire_angle=0.0;
3870 int32_t wx=0, wy=0, wdir=dir;
3871
3872 if(!seekhero)
3873 {
3874 switch(dir)
3875 {
3876 case down:
3877 fire_angle=PI*(int64_t(zc_oldrand()%20)+10)/40;
3878 wx=x;
3879 wy=y+8;
3880 break;
3881
3882 case -1:
3883 case up:
3884 fire_angle=PI*(int64_t(zc_oldrand()%20)+50)/40;
3885 wx=x;
3886 wy=y-8;
3887 break;
3888
3889 case left:
3890 fire_angle=PI*(int64_t(zc_oldrand()%20)+30)/40;
3891 wx=x-8;
3892 wy=y;
3893 break;
3894
3895 case right:
3896 fire_angle=PI*(int64_t(zc_oldrand()%20)+70)/40;
3897 wx=x+8;
3898 wy=y;
3899 break;
3900 }
3901
3902 if(wpn==ewFlame || wpn==ewFlame2)
3903 {
3904 if(fire_angle==-PI || fire_angle==PI) wdir=left;
3905 else if(fire_angle==-PI/2) wdir=up;
3906 else if(fire_angle==PI/2) wdir=down;
3907 else if(fire_angle==0) wdir=right;
3908 else if(fire_angle<-PI/2) wdir=l_up;
3909 else if(fire_angle<0) wdir=r_up;
3910 else if(fire_angle<(PI/2)) wdir=r_down;
3911 else if(fire_angle<PI) wdir=l_down;
3912 }
3913 }
3914 else
3915 {
3916 wx = x;
3917 wy = y;
3918 }
3919
3920 addEwpn(wx,wy,z,wpn,2,wdp,seekhero ? 0xFF : wdir, getUID(), 0, fakez);
3921 sfx(wpnsfx(wpn),pan(int32_t(x)));
3922
3923 int32_t i=Ewpns.Count()-1;
3924 weapon *ew = (weapon*)(Ewpns.spr(i));
3925 ew->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
3926
3927 if(!seekhero && (zc_oldrand()&4))
3928 {
3929 ew->angular=true;
3930 ew->angle=fire_angle;
3931 }
3932
3933 if(wpn==ewFlame && wpnsbuf[ewFLAME].frames>1)
3934 {
3935 ew->aframe=zc_oldrand()%wpnsbuf[ewFLAME].frames;
3936 if ( ew->do_animation ) ew->tile+=ew->aframe;
3937 }
3938
3939 for(int32_t j=Ewpns.Count()-1; j>0; j--)
3940 {
3941 Ewpns.swap(j,j-1);
3942 }
3943 }
3944
3945 8 void enemy::FireWeapon()
3946 {
3947 /*
3948 * Type:
3949 * 0x01: Boss fireball
3950 * 0x02: Seeks Hero
3951 * 0x04: Fast projectile
3952 * 0x00-0x30: If 0x02, slants toward (type>>3)-1
3953 */
3954
3955
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (wpn < 1) return;
3956
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
8 if(wpn<wEnemyWeapons && dmisc1!=9 && dmisc1!=10 && (wpn < wScript1 && wpn > wScript10) ) // Summoning doesn't require weapons
3957 return;
3958
3959
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if(wpn==ewFireTrail && dmisc1>=e1t3SHOTS && dmisc1<=e1t8SHOTS)
3960 dmisc1 = e1tEACHTILE;
3961
3962 8 int32_t xoff = 0;
3963 8 int32_t yoff = 0;
3964
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ( SIZEflags&guyflagOVERRIDE_HIT_WIDTH )
3965 {
3966 xoff += (hxsz/2)-8;
3967 //Z_scripterrlog("width flag enabled. xoff = %d\n", xoff);
3968 }
3969
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ( SIZEflags&guyflagOVERRIDE_HIT_HEIGHT )
3970 {
3971 yoff += (hysz/2)-8;
3972 //Z_scripterrlog("width flag enabled. yoff = %d\n", yoff);
3973 }
3974
3975
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 switch(dmisc1)
3976 {
3977 case e1t5SHOTS: //BS-Aquamentus
3978 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,2+(((dir^left)+5)<<3),wdp,dir,-1, getUID(),false));
3979 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
3980 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,2+(((dir^right)+5)<<3),wdp,dir,-1, getUID(),false));
3981 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
3982
3983 [[fallthrough]];
3984 case e1t3SHOTSFAST:
3985 case e1t3SHOTS: //Aquamentus
3986 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,2+(((dir^left)+1)<<3)+(dmisc1==e1t3SHOTSFAST ? 4:0),wdp,dir,-1, getUID(),false));
3987 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
3988 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,2+(((dir^right)+1)<<3)+(dmisc1==e1t3SHOTSFAST ? 4:0),wdp,dir,-1, getUID(),false));
3989 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
3990
3991 [[fallthrough]];
3992 default:
3993
10/20
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8 times.
✗ Branch 19 not taken.
8 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,2+(dmisc1==e1t3SHOTSFAST || dmisc1==e1tFAST ? 4:0),wdp,wpn==ewFireball2 || wpn==ewFireball ? 0:dir,-1, getUID(),false));
3994 8 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
3995 8 sfx(wpnsfx(wpn),pan(int32_t(x)));
3996 8 break;
3997
3998 case e1tSLANT:
3999 {
4000 int32_t slant = 0;
4001
4002 if(((Hero.x-x) < -8 && dir==up) || ((Hero.x-x) > 8 && dir==down) || ((Hero.y-y) < -8 && dir==left) || ((Hero.y-y) > 8 && dir==right))
4003 slant = left;
4004 else if(((Hero.x-x) > 8 && dir==up) || ((Hero.x-x) < -8 && dir==down) || ((Hero.y-y) > 8 && dir==left) || ((Hero.y-y) < -8 && dir==right))
4005 slant = right;
4006
4007 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,2+(((dir^slant)+1)<<3),wdp,wpn==ewFireball2 || wpn==ewFireball ? 0:dir,-1, getUID(),false));
4008 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4009 sfx(wpnsfx(wpn),pan(int32_t(x)));
4010 break;
4011 }
4012
4013 case e1t8SHOTS: //Fire Wizzrobe
4014 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,l_up,-1, getUID(),false));
4015 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4016 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4017 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,l_down,-1, getUID(),false));
4018 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4019 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4020 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,r_up,-1, getUID(),false));
4021 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4022 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4023 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,r_down,-1, getUID(),false));
4024 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4025 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4026
4027 [[fallthrough]];
4028 case e1t4SHOTS: //Stalfos 3
4029 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,up,-1, getUID(),false));
4030 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4031 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4032 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,down,-1, getUID(),false));
4033 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4034 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4035 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,left,-1, getUID(),false));
4036 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4037 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4038 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,0,wdp,right,-1, getUID(),false));
4039 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
4040 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
4041 sfx(wpnsfx(wpn),pan(int32_t(x)));
4042 break;
4043
4044 case e1tSUMMON: // Bat Wizzrobe
4045 {
4046 //al_trace("Summon Bats\n");
4047 //zprint2("Summon Bats\n");
4048 if(dmisc4==0) break; // Summon 0
4049
4050 int32_t bc=0;
4051
4052 for(int32_t gc=0; gc<guys.Count(); gc++)
4053 {
4054 if((((enemy*)guys.spr(gc))->id) == dmisc3)
4055 {
4056 ++bc;
4057 }
4058 }
4059
4060 if(bc<=40) // Not too many enemies
4061 {
4062 int32_t kids = guys.Count();
4063 int32_t bats=(zc_oldrand()%zc_max(1,dmisc4))+1;
4064
4065 for(int32_t i=0; i<bats; i++)
4066 {
4067 //zprint2("summon\n");
4068 //al_trace("summon\n");
4069 if(addchild(x,y,dmisc3,-10, this->script_UID))
4070 {
4071 ((enemy*)guys.spr(kids+i))->count_enemy = false;
4072 //((enemy*)guys.spr(guys.Count()-1))->parent_script_UID = this->script_UID;
4073 //zprint2("Summoner Script UID: %d\n",this->script_UID);
4074
4075 }
4076 }
4077
4078 sfx(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,pan(int32_t(x)));
4079 }
4080
4081 break;
4082 }
4083
4084 case e1tSUMMONLAYER: // Summoner
4085 {
4086 if(count_layer_enemies()==0)
4087 {
4088 break;
4089 }
4090
4091 int32_t kids = guys.Count();
4092
4093 if(kids<40)
4094 {
4095 int32_t newguys=(zc_oldrand()%3)+1;
4096 bool summoned=false;
4097
4098 for(int32_t i=0; i<newguys; i++)
4099 {
4100 int32_t id2=vbound(random_layer_enemy(),eSTART,eMAXGUYS-1);
4101 int32_t x2=0;
4102 int32_t y2=0;
4103
4104 for(int32_t k=0; k<20; ++k)
4105 {
4106 x2=16*((zc_oldrand()%12)+2);
4107 y2=16*((zc_oldrand()%7)+2);
4108
4109 if((!m_walkflag(x2,y2,0,dir))&&((abs(x2-Hero.getX())>=32)||(abs(y2-Hero.getY())>=32)))
4110 {
4111 //zprint2("summon\n");
4112 //al_trace("summon\n");
4113 if(addchild(x2,y2,get_bit(quest_rules,qr_ENEMIESZAXIS) ? 64 : 0,id2,-10, this->script_UID))
4114 {
4115 ((enemy*)guys.spr(kids+i))->count_enemy = false;
4116 //((enemy*)guys.spr(guys.Count()-1))->parent_script_UID = this->script_UID;
4117 if (get_bit(quest_rules,qr_ENEMIESZAXIS) && (((enemy*)guys.spr(kids+i))->moveflags & FLAG_USE_FAKE_Z))
4118 {
4119 ((enemy*)guys.spr(kids+i))->fakez = 64;
4120 ((enemy*)guys.spr(kids+i))->z = 0;
4121 }
4122 }
4123
4124 summoned=true;
4125 break;
4126 }
4127 }
4128 }
4129
4130 if(summoned)
4131 {
4132 sfx(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,pan(int32_t(x)));
4133 }
4134 }
4135
4136 break;
4137 }
4138 }
4139 8 }
4140
4141
4142 // Hit the shield(s)?
4143 // Apparently, this function is only used for hookshots...
4144 bool enemy::hitshield(int32_t wpnx, int32_t wpny, int32_t xdir)
4145 {
4146 if(!(family==eeWALK || family==eeFIRE || family==eeOTHER))
4147 return false;
4148
4149 bool ret = false;
4150
4151 // TODO: There must be some bitwise operations that can simplify this...
4152 if(wpny > y) ret = ((flags&inv_front && xdir==down) || (flags&inv_back && xdir==up) || (flags&inv_left && xdir==left) || (flags&inv_right && xdir==right));
4153 else if(wpny < y) ret = ((flags&inv_front && xdir==up) || (flags&inv_back && xdir==down) || (flags&inv_left && xdir==right) || (flags&inv_right && xdir==left));
4154
4155 if(wpnx < x) ret = ret || ((flags&inv_front && xdir==left) || (flags&inv_back && xdir==right) || (flags&inv_left && xdir==up) || (flags&inv_right && xdir==down));
4156 else if(wpnx > x) ret = ret || ((flags&inv_front && xdir==right) || (flags&inv_back && xdir==left) || (flags&inv_left && xdir==down) || (flags&inv_right && xdir==up));
4157
4158 return ret;
4159 }
4160
4161
4162 //! Weapon Editor for 2.6
4163 //To hell with this. I'm writing new functions to resolve weapon type and defence. -Z
4164
4165
4166 //converts a wqeapon ID to its defence index.
4167 7 int32_t weaponToDefence(int32_t wid)
4168 {
4169
2/44
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
7 switch(wid)
4170 {
4171 case wNone: return -1;
4172 1 case wSword: return edefSWORD;
4173 6 case wBeam: return edefBEAM;
4174 case wBrang: return edefBRANG;
4175 case wBomb: return edefBOMB;
4176 case wSBomb: return edefSBOMB;
4177 case wLitBomb: return edefBOMB;
4178 case wLitSBomb: return edefSBOMB;
4179 case wArrow: return edefARROW;
4180 case wFire: return edefFIRE;
4181 case wWhistle:
4182 {
4183 //al_trace("Weapon resolved as a whistle, using edef: %s\n", "edefWhistle");
4184 return edefWhistle;
4185 }
4186 case wBait: return edefBAIT;
4187 case wWand: return edefWAND;
4188 case wMagic: return edefMAGIC;
4189 case wCatching: return -1;
4190 case wWind: return edefWIND;
4191 case wRefMagic: return edefREFMAGIC;
4192 case wRefFireball: return edefREFBALL;
4193 case wRefRock: return edefREFROCK;
4194 case wHammer: return edefHAMMER;
4195 case wHookshot: return edefHOOKSHOT;
4196 case wHSHandle: return edefHOOKSHOT;
4197 case wHSChain: return edefHOOKSHOT;
4198 case wSSparkle: return edefSPARKLE;
4199 case wFSparkle: return edefSPARKLE;
4200 case wSmack: return -1; // is this the candle object?
4201 case wPhantom: return -1; //engine created visual effects.
4202 case wCByrna: return edefBYRNA;
4203 case wRefBeam: return edefREFBEAM;
4204 case wStomp: return edefSTOMP;
4205 case wScript1: return edefSCRIPT01;
4206 case wScript2: return edefSCRIPT02;
4207 case wScript3: return edefSCRIPT03;
4208 case wScript4: return edefSCRIPT04;
4209 case wScript5: return edefSCRIPT05;
4210 case wScript6: return edefSCRIPT06;
4211 case wScript7: return edefSCRIPT07;
4212 case wScript8: return edefSCRIPT08;
4213 case wScript9: return edefSCRIPT09;
4214 case wScript10: return edefSCRIPT10;
4215 case wIce: return edefICE;
4216 case wSound: return edefSONIC;
4217 case wThrown: return edefTHROWN;
4218 //case wPot: return edefPOT;
4219 // case wLitZap: return edefELECTRIC;
4220 // case wZ3Sword: return edefZ3SWORD;
4221 // case wLASWord: return edefLASWORD;
4222 // case wSpinAttk: return edefSPINATTK;
4223 // case wShield: return edefSHIELD;
4224 // case wTrowel: return edefTROWEL;
4225
4226 default: return -1;
4227 }
4228 7 }
4229
4230 7 int32_t getDefType(weapon *w)
4231 {
4232 7 int32_t id = getWeaponID(w);
4233 7 int32_t edef = weaponToDefence(id);
4234
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(edef == edefHOOKSHOT)
4235 {
4236 if(w->family_class == itype_switchhook)
4237 return edefSwitchHook;
4238 }
4239 7 return edef;
4240 7 }
4241
4242 14 int32_t getWeaponID(weapon *w)
4243 {
4244 14 int32_t usewpn = w->useweapon;
4245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 return (usewpn > 0) ? usewpn : w->id;
4246 }
4247
4248 7 int32_t enemy::resolveEnemyDefence(weapon *w)
4249 {
4250 //sword edef is 9, but we're reading it at 0
4251 //,
4252 7 int32_t weapondef = 0;
4253 7 int32_t wdeftype = getDefType(w);
4254 7 int32_t usedef = w->usedefence;
4255
4256
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 if ( usedef > 0 && (wdeftype < 0 || wdeftype >= edefLAST255 || defense[wdeftype] == 0))
4257 {
4258 weapondef = usedef*-1;
4259 }
4260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 else if(unsigned(wdeftype) < edefLAST255)
4261 {
4262 7 weapondef = wdeftype;
4263 7 }
4264 7 return weapondef;
4265 }
4266
4267 7 byte get_def_ignrflag(int32_t edef)
4268 {
4269
1/3
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
7 switch(edef)
4270 {
4271 case edIGNORE:
4272 case edIGNOREL1:
4273 case edSTUNORIGNORE:
4274 return WPNUNB_IGNR;
4275 case edSTUNORCHINK:
4276 case edCHINK:
4277 case edCHINKL1:
4278 case edCHINKL2:
4279 case edCHINKL4:
4280 case edCHINKL6:
4281 case edCHINKL8:
4282 case edCHINKL10:
4283 case edLEVELCHINK2:
4284 case edLEVELCHINK3:
4285 case edLEVELCHINK4:
4286 case edLEVELCHINK5:
4287 return WPNUNB_BLOCK;
4288 }
4289 7 return 0;
4290 7 }
4291
4292 7 int32_t conv_edef_unblockable(int32_t edef, byte unblockable)
4293 {
4294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(!(unblockable&get_def_ignrflag(edef))) return edef;
4295 switch(edef)
4296 {
4297 case edIGNORE:
4298 case edIGNOREL1:
4299 case edCHINK:
4300 case edCHINKL1:
4301 case edCHINKL2:
4302 case edCHINKL4:
4303 case edCHINKL6:
4304 case edCHINKL8:
4305 case edCHINKL10:
4306 case edLEVELCHINK2:
4307 case edLEVELCHINK3:
4308 case edLEVELCHINK4:
4309 case edLEVELCHINK5:
4310 return edNORMAL;
4311 case edSTUNORIGNORE:
4312 case edSTUNORCHINK:
4313 return edSTUNONLY;
4314 }
4315 return edef;
4316 7 }
4317
4318 // Do we do damage?
4319 // 0: takehit returns 0
4320 // 1: takehit returns 1
4321 // -1: do damage
4322 //The input from resolveEnemyDefence() for the param 'edef' is negative if a specific defence RESULT is being used.
4323 7 int32_t enemy::defendNew(int32_t wpnId, int32_t *power, int32_t edef, byte unblockable) //May need *wpn to set return on brangs and hookshots
4324 {
4325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(switch_hooked) return 0;
4326 7 int32_t tempx = x;
4327 7 int32_t tempy = y;
4328 7 int32_t the_defence = 0;
4329
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if ( edef < 0 ) //we are using a specific base default defence for a weapon
4330 {
4331 the_defence = edef*-1; //A specific defence type.
4332 }
4333 7 else the_defence = defense[edef];
4334
4335 7 the_defence = conv_edef_unblockable(the_defence, unblockable);
4336
4337
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if(shieldCanBlock && !(unblockable&WPNUNB_SHLD))
4338 {
4339 switch(the_defence)
4340 {
4341 case edIGNORE:
4342 return 0;
4343 case edIGNOREL1:
4344 case edSTUNORIGNORE:
4345 if(*power <= 0)
4346 return 0;
4347 }
4348 sfx(WAV_CHINK,pan(int32_t(x)));
4349 return 1;
4350 }
4351
4352 7 int32_t new_id = id;
4353 7 int32_t effect_type = dmisc15;
4354 7 int32_t delay_timer = 90;
4355 7 enemy *gleeok = NULL;
4356 7 enemy *ptra = NULL;
4357 7 int32_t c = 0;
4358
4359
1/29
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 7 times.
7 switch(the_defence)
4360 {
4361 case edREPLACE:
4362 {
4363 sclk = 0;
4364 if ( dmisc16 > 0 ) new_id = dmisc16;
4365 else new_id = id+1;
4366 if ( new_id > 511 ) new_id = id; //Sanity bound to legal enemy IDs.
4367 if ( dmisc17 > 0 ) delay_timer = dmisc17;
4368 //if ( dmisc18 > 0 ) dummy_wpn_id = dmisc18;
4369
4370 //Z_scripterrlog("new id is %d\n", new_id);
4371 switch(guysbuf[new_id&0xFFF].family)
4372 {
4373 //Fixme: possible enemy memory leak. (minor)
4374 case eeWALK:
4375 {
4376 enemy *e = new eStalfos(x,y,new_id,clk);
4377 guys.add(e);
4378 }
4379 break;
4380
4381 case eeLEV:
4382 {
4383 enemy *e = new eLeever(x,y,new_id,clk);
4384 guys.add(e);
4385 }
4386 break;
4387
4388 case eeTEK:
4389 {
4390 enemy *e = new eTektite(x,y,new_id,clk);
4391 guys.add(e);
4392 }
4393 break;
4394
4395 case eePEAHAT:
4396 {
4397 enemy *e = new ePeahat(x,y,new_id,clk);
4398 guys.add(e);
4399 }
4400 break;
4401
4402 case eeZORA:
4403 {
4404 enemy *e = new eZora(x,y,new_id,clk);
4405 guys.add(e);
4406 }
4407 break;
4408
4409 case eeGHINI:
4410 {
4411 enemy *e = new eGhini(x,y,new_id,clk);
4412 guys.add(e);
4413 }
4414 break;
4415
4416 case eeKEESE:
4417 {
4418 enemy *e = new eKeese(x,y,new_id,clk);
4419 guys.add(e);
4420 }
4421 break;
4422
4423 case eeWIZZ:
4424 {
4425 enemy *e = new eWizzrobe(x,y,new_id,clk);
4426 guys.add(e);
4427 }
4428 break;
4429
4430 case eePROJECTILE:
4431 {
4432 enemy *e = new eProjectile(x,y,new_id,clk);
4433 guys.add(e);
4434 }
4435 break;
4436
4437 case eeWALLM:
4438 {
4439 enemy *e = new eWallM(x,y,new_id,clk);
4440 guys.add(e);
4441 }
4442 break;
4443
4444 case eeAQUA:
4445 {
4446 enemy *e = new eAquamentus(x,y,new_id,clk);
4447 guys.add(e);
4448 e->x = x;
4449 e->y = y;
4450 }
4451 break;
4452
4453 case eeMOLD:
4454 {
4455 enemy *e = new eMoldorm(x,y,new_id,zc_max(1,zc_min(254,guysbuf[new_id&0xFFF].misc1)));
4456 guys.add(e);
4457 e->x = x;
4458 e->y = y;
4459 }
4460 break;
4461
4462 case eeMANHAN:
4463 {
4464 enemy *e = new eManhandla(x,y,new_id,clk);
4465 guys.add(e);
4466 e->x = x;
4467 e->y = y;
4468 }
4469 break;
4470
4471 case eeGLEEOK:
4472 {
4473 *power = 0;
4474 gleeok = new eGleeok(x,y,new_id,guysbuf[new_id&0xFFF].misc1);
4475 guys.add(gleeok);
4476 ((enemy*)guys.spr(guys.Count()-1))->hclk = delay_timer;
4477 //((enemy*)guys.spr(guys.Count()-1))->stunclk = delay_timer;
4478 new_id &= 0xFFF;
4479 int32_t head_cnt = zc_max(1,zc_min(254,guysbuf[new_id&0xFFF].misc1));
4480 Z_scripterrlog("Gleeok head count is %d\n",head_cnt);
4481 for(int32_t i=0; i<head_cnt; i++)
4482 {
4483 //enemy *e = new esGleeok(x,y,new_id+0x1000,clk,gleeok);
4484 if(!guys.add(new esGleeok((zfix)x,(zfix)y,new_id+0x1000,c, gleeok)))
4485 {
4486 al_trace("Gleeok head %d could not be created!\n",i+1);
4487
4488 for(int32_t j=0; j<i+1; j++)
4489 {
4490 guys.del(guys.Count()-1);
4491 }
4492
4493 break;
4494 }
4495 else
4496 {
4497 ((enemy*)guys.spr(guys.Count()-1))->hclk = delay_timer;
4498 //((enemy*)guys.spr(guys.Count()-1))->stunclk = delay_timer;
4499 }
4500
4501 c-=guysbuf[new_id].misc4;
4502 //gleeok->x = x;
4503 //gleeok->y = y;
4504 //gleeok = e;
4505 }
4506 return 1;
4507 }
4508
4509 case eeGHOMA:
4510 {
4511 enemy *e = new eGohma(x,y,new_id,clk);
4512 guys.add(e);
4513 e->x = x;
4514 e->y = y;
4515 }
4516 break;
4517
4518 case eeLANM:
4519 {
4520 enemy *e = new eLanmola(x,y,new_id,zc_max(1,zc_min(253,guysbuf[new_id&0xFFF].misc1)));
4521 guys.add(e);
4522 e->x = x;
4523 e->y = y;
4524 }
4525 break;
4526
4527 case eeGANON:
4528 {
4529 enemy *e = new eGanon(x,y,new_id,clk);
4530 guys.add(e);
4531 e->x = x;
4532 e->y = y;
4533 }
4534 break;
4535
4536 case eeFAIRY:
4537 {
4538 enemy *e = new eItemFairy(x,y,new_id+0x1000*clk,clk);
4539 guys.add(e);
4540 e->x = x;
4541 e->y = y;
4542 }
4543 break;
4544
4545 case eeFIRE:
4546 {
4547 enemy *e = new eFire(x,y,new_id,clk);
4548 guys.add(e);
4549 e->x = x;
4550 e->y = y;
4551 }
4552 break;
4553
4554 case eeOTHER:
4555 {
4556 enemy *e = new eOther(x,y,new_id,clk);
4557 guys.add(e);
4558 e->x = x;
4559 e->y = y;
4560 }
4561 break;
4562
4563 case eeSPINTILE:
4564 {
4565 enemy *e = new eSpinTile(x,y,new_id,clk);
4566 guys.add(e);
4567 e->x = x;
4568 e->y = y;
4569 }
4570 break;
4571
4572 // and these enemies use the misc10/misc2 value
4573 case eeROCK:
4574 {
4575 switch(guysbuf[new_id&0xFFF].misc10)
4576 {
4577 case 1:
4578 {
4579 enemy *e = new eBoulder(x,y,new_id,clk);
4580 guys.add(e);
4581 e->x = x;
4582 e->y = y;
4583 }
4584 break;
4585
4586 case 0:
4587 default:
4588 {
4589 enemy *e = new eRock(x,y,new_id,clk);
4590 guys.add(e);
4591 e->x = x;
4592 e->y = y;
4593 }
4594 break;
4595 }
4596
4597 break;
4598 }
4599
4600 case eeTRAP:
4601 {
4602 switch(guysbuf[new_id&0xFFF].misc2)
4603 {
4604 case 1:
4605 {
4606 enemy *e = new eTrap2(x,y,new_id,clk);
4607 guys.add(e);
4608 e->x = x;
4609 e->y = y;
4610 }
4611 break;
4612
4613 case 0:
4614 default:
4615 {
4616 enemy *e = new eTrap(x,y,new_id,clk);
4617 guys.add(e);
4618 e->x = x;
4619 e->y = y;
4620 }
4621 break;
4622 }
4623
4624 break;
4625 }
4626
4627 case eeDONGO:
4628 {
4629 switch(guysbuf[new_id&0xFFF].misc10)
4630 {
4631 case 1:
4632 {
4633 enemy *e = new eDodongo2(x,y,new_id,clk);
4634 guys.add(e);
4635 e->x = x;
4636 e->y = y;
4637 }
4638 break;
4639
4640 case 0:
4641 default:
4642 {
4643 enemy *e = new eDodongo(x,y,new_id,clk);
4644 guys.add(e);
4645 e->x = x;
4646 e->y = y;
4647 }
4648 break;
4649 }
4650
4651 break;
4652 }
4653
4654 case eeDIG:
4655 {
4656 switch(guysbuf[new_id&0xFFF].misc10)
4657 {
4658 case 1:
4659 {
4660 enemy *e = new eLilDig(x,y,new_id,clk);
4661 guys.add(e);
4662 e->x = x;
4663 e->y = y;
4664 }
4665 break;
4666
4667 case 0:
4668 default:
4669 {
4670 enemy *e = new eBigDig(x,y,new_id,clk);
4671 guys.add(e);
4672 e->x = x;
4673 e->y = y;
4674 }
4675 break;
4676 }
4677
4678 break;
4679 }
4680
4681 case eePATRA:
4682 {
4683 switch(guysbuf[new_id&0xFFF].misc10)
4684 {
4685 case 1:
4686 {
4687 if (get_bit(quest_rules,qr_HARDCODED_BS_PATRA))
4688 {
4689 enemy *e = new ePatraBS(x,y,new_id,clk);
4690 guys.add(e);
4691 e->x = x;
4692 e->y = y;
4693 break;
4694 }
4695 }
4696 [[fallthrough]];
4697 case 0:
4698 default:
4699 {
4700 enemy *e = new ePatra(x,y,new_id,clk);
4701 guys.add(e);
4702 e->x = x;
4703 e->y = y;
4704 }
4705 break;
4706 }
4707
4708 break;
4709 }
4710
4711 case eeGUY:
4712 {
4713 switch(guysbuf[new_id&0xFFF].misc10)
4714 {
4715 case 1:
4716 {
4717 enemy *e = new eTrigger(x,y,new_id,clk);
4718 guys.add(e);
4719 }
4720 break;
4721
4722 case 0:
4723 default:
4724 {
4725 enemy *e = new eNPC(x,y,new_id,clk);
4726 guys.add(e);
4727 }
4728 break;
4729 }
4730
4731 break;
4732 }
4733
4734 case eeSCRIPT01:
4735 case eeSCRIPT02:
4736 case eeSCRIPT03:
4737 case eeSCRIPT04:
4738 case eeSCRIPT05:
4739 case eeSCRIPT06:
4740 case eeSCRIPT07:
4741 case eeSCRIPT08:
4742 case eeSCRIPT09:
4743 case eeSCRIPT10:
4744 case eeSCRIPT11:
4745 case eeSCRIPT12:
4746 case eeSCRIPT13:
4747 case eeSCRIPT14:
4748 case eeSCRIPT15:
4749 case eeSCRIPT16:
4750 case eeSCRIPT17:
4751 case eeSCRIPT18:
4752 case eeSCRIPT19:
4753 case eeSCRIPT20:
4754 {
4755 enemy *e = new eScript(x,y,new_id,clk);
4756 guys.add(e);
4757 e->x = x;
4758 e->y = y;
4759 break;
4760 }
4761
4762
4763 case eeFFRIENDLY01:
4764 case eeFFRIENDLY02:
4765 case eeFFRIENDLY03:
4766 case eeFFRIENDLY04:
4767 case eeFFRIENDLY05:
4768 case eeFFRIENDLY06:
4769 case eeFFRIENDLY07:
4770 case eeFFRIENDLY08:
4771 case eeFFRIENDLY09:
4772 case eeFFRIENDLY10:
4773 {
4774 enemy *e = new eFriendly(x,y,new_id,clk);
4775 guys.add(e);
4776 e->x = x;
4777 e->y = y;
4778 break;
4779 }
4780
4781
4782 default: break;
4783 }
4784
4785 // add segments of segmented enemies
4786 int32_t c=0;
4787
4788 switch(guysbuf[new_id&0xFFF].family)
4789 {
4790 case eeMOLD:
4791 {
4792 byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
4793 new_id &= 0xFFF;
4794
4795 for(int32_t i=0; i<zc_max(1,zc_min(254,guysbuf[new_id].misc1)); i++)
4796 {
4797 //christ this is messy -DD
4798 int32_t segclk = -i*((int32_t)(8.0/(zslongToFix(guysbuf[new_id&0xFFF].step*100))));
4799
4800 if(!guys.add(new esMoldorm((zfix)x,(zfix)y,new_id+0x1000,segclk)))
4801 {
4802 al_trace("Moldorm segment %d could not be created!\n",i+1);
4803
4804 for(int32_t j=0; j<i+1; j++)
4805 guys.del(guys.Count()-1);
4806
4807 return 0;
4808 }
4809
4810 if(i>0)
4811 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
4812
4813
4814 }
4815
4816 break;
4817 }
4818
4819 case eeLANM:
4820 {
4821 new_id &= 0xFFF;
4822 int32_t shft = guysbuf[new_id].misc2;
4823 byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
4824 enemy *e = new esLanmola((zfix)x,(zfix)y,new_id+0x1000,0);
4825
4826 if(!guys.add(e))
4827 {
4828 al_trace("Lanmola segment 1 could not be created!\n");
4829 guys.del(guys.Count()-1);
4830 return 0;
4831 }
4832 e->x = x;
4833 e->y = y;
4834
4835
4836
4837 for(int32_t i=1; i<zc_max(1,zc_min(253,guysbuf[new_id&0xFFF].misc1)); i++)
4838 {
4839 enemy *e2 = new esLanmola((zfix)x,(zfix)y,new_id+0x2000,-(i<<shft));
4840 if(!guys.add(e2))
4841 {
4842 al_trace("Lanmola segment %d could not be created!\n",i+1);
4843
4844 for(int32_t j=0; j<i+1; j++)
4845 guys.del(guys.Count()-1);
4846
4847 return 0;
4848 }
4849 e2->x = x;
4850 e2->y = y;
4851
4852 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
4853
4854 }
4855 }
4856 break;
4857
4858 case eeMANHAN:
4859 new_id &= 0xFFF;
4860
4861 for(int32_t i=0; i<((!(guysbuf[new_id].misc2))?4:8); i++)
4862 {
4863 if(!guys.add(new esManhandla((zfix)x,(zfix)y,new_id+0x1000,i)))
4864 {
4865 al_trace("Manhandla head %d could not be created!\n",i+1);
4866
4867 for(int32_t j=0; j<i+1; j++)
4868 {
4869 guys.del(guys.Count()-1);
4870 }
4871
4872 return 0;
4873 }
4874
4875
4876 ((enemy*)guys.spr(guys.Count()-1))->frate=guysbuf[new_id].misc1;
4877 }
4878
4879 break;
4880
4881 case eeGLEEOK:
4882 {
4883 /*
4884 new_id &= 0xFFF;
4885 int32_t head_cnt = zc_max(1,zc_min(254,guysbuf[new_id&0xFFF].misc1));
4886 Z_scripterrlog("Gleeok head count is %d\n",head_cnt);
4887 for(int32_t i=0; i<head_cnt; i++)
4888 {
4889 //enemy *e = new esGleeok(x,y,new_id+0x1000,clk,gleeok);
4890 if(!guys.add(new esGleeok((zfix)x,(zfix)y,new_id+0x1000,c, gleeok)))
4891 {
4892 al_trace("Gleeok head %d could not be created!\n",i+1);
4893
4894 for(int32_t j=0; j<i+1; j++)
4895 {
4896 guys.del(guys.Count()-1);
4897 }
4898
4899 break;
4900 }
4901
4902 c-=guysbuf[new_id].misc4;
4903 */
4904
4905 // }
4906 }
4907 break;
4908
4909
4910 case eePATRA:
4911 {
4912 new_id &= 0xFFF;
4913 int32_t outeyes = 0;
4914 ptra = new ePatraBS((zfix)x,(zfix)y,id,clk);
4915
4916 for(int32_t i=0; i<zc_min(254,guysbuf[new_id&0xFFF].misc1); i++)
4917 {
4918 if(!((guysbuf[new_id].misc10&&get_bit(quest_rules,qr_HARDCODED_BS_PATRA))?guys.add(new esPatraBS((zfix)x,(zfix)y,new_id+0x1000,i,ptra)):guys.add(new esPatra((zfix)x,(zfix)y,new_id+0x1000,i,ptra))))
4919 {
4920 al_trace("Patra outer eye %d could not be created!\n",i+1);
4921
4922 for(int32_t j=0; j<i+1; j++)
4923 guys.del(guys.Count()-1);
4924
4925 return 0;
4926 }
4927 else
4928 outeyes++;
4929
4930
4931 }
4932
4933 for(int32_t i=0; i<zc_min(254,guysbuf[new_id&0xFFF].misc2); i++)
4934 {
4935 if(!guys.add(new esPatra((zfix)x,(zfix)y,new_id+0x1000,i,ptra)))
4936 {
4937 al_trace("Patra inner eye %d could not be created!\n",i+1);
4938
4939 for(int32_t j=0; j<i+1+zc_min(254,outeyes); j++)
4940 guys.del(guys.Count()-1);
4941
4942 return 0;
4943 }
4944
4945
4946 }
4947 delete ptra;
4948 break;
4949 }
4950 }
4951
4952
4953
4954 ((enemy*)guys.spr(guys.Count()-1))->count_enemy = true;
4955 ((enemy*)guys.spr(guys.Count()-1))->stunclk = delay_timer;
4956 ((enemy*)guys.spr(guys.Count()-1))->dir = this->dir;
4957 ((enemy*)guys.spr(guys.Count()-1))->scale = this->scale;
4958 ((enemy*)guys.spr(guys.Count()-1))->angular = this->angular;
4959 ((enemy*)guys.spr(guys.Count()-1))->angle = this->angle;
4960 ((enemy*)guys.spr(guys.Count()-1))->rotation = this->rotation;
4961 //((enemy*)guys.spr(guys.Count()-1))->mainguy = this->mainguy; //This might mean that it is a core.
4962 ((enemy*)guys.spr(guys.Count()-1))->itemguy = this->itemguy;
4963 ((enemy*)guys.spr(guys.Count()-1))->leader = this->leader;
4964 ((enemy*)guys.spr(guys.Count()-1))->hclk = delay_timer;
4965 ((enemy*)guys.spr(guys.Count()-1))->script_spawned = this->script_spawned;
4966 ((enemy*)guys.spr(guys.Count()-1))->script_UID = this->script_UID;
4967 ((enemy*)guys.spr(guys.Count()-1))->sclk = 0;
4968
4969
4970 item_set = 0; //Do not make a drop.
4971
4972 switch(effect_type)
4973 {
4974 case -7:
4975 {
4976 weapon *w = new weapon(x,y-fakez,z,wBomb,0,wdp,0,-1,getUID(),false, 0);
4977 Lwpns.add(w);
4978 break;
4979 }
4980 case -6:
4981 {
4982 weapon *w = new weapon(x,y-fakez,z,wSBomb,0,wdp,0,-1,getUID(),false, 0);
4983 Lwpns.add(w);
4984 break;
4985 }
4986 case -5:
4987 {
4988 weapon *w = new weapon(x,y-fakez,z,wBomb,effect_type,0,0,Hero.getUID(), txsz, tysz);
4989 Lwpns.add(w);
4990 break;
4991 }
4992 case -4:
4993 {
4994 weapon *w = new weapon(x,y-fakez,z,wSBomb,effect_type,0,0,Hero.getUID(), txsz, tysz);
4995 Lwpns.add(w);
4996 break;
4997 }
4998 case -3: explode(1); break;
4999 case -2: explode(2); break;
5000 case -1: explode(0); break;
5001 case 0: break;
5002
5003 default:
5004 {
5005 //Dummy weapon function
5006 if ( effect_type > 255 ) effect_type = 0; //Sanity bound the sprite ID.
5007 weapon *w = new weapon(x,y-fakez,z,wSSparkle,effect_type,0,0,Hero.getUID(), txsz, tysz,0,0,0,0,0,0,0);
5008 Lwpns.add(w);
5009 break;
5010 }
5011 }
5012
5013
5014 yofs = -32768;
5015 switch(guysbuf[new_id&0xFFF].family)
5016 {
5017 case eeGLEEOK:
5018 {
5019 Z_scripterrlog("Replacing a gleeok.\n");
5020 enemy *tempenemy = (enemy *) guys.getByUID(parentCore);
5021 hp = -999;
5022 tempenemy->hp = -999;
5023 break;
5024
5025 }
5026 default:
5027 hp = -1000; break;
5028 }
5029 ++game->guys[(currmap*MAPSCRSNORMAL)+currscr];
5030 return 1;
5031
5032 }
5033 case edSPLIT:
5034 {
5035 //int32_t ex = x; int32_t ey = y;
5036 //al_trace("edSplit dmisc3: %d\n", dmisc3);
5037 //al_trace("edSplit dmisc4: %d\n", dmisc4);
5038 /*
5039 if ( txsx > 1 )
5040 {
5041 ex += ( txsz-1 ) * 8; //from its middle
5042 }
5043 if ( tysx > 1 )
5044 {
5045 ey += ( tysz-1 ) * 8; //from its middle
5046 }
5047 */
5048 for ( int32_t q = 0; q < dmisc4; q++ )
5049 {
5050
5051 //addenemy((x+(txsz*16)/2),(y+(tysz*16)/2),dmisc3+0x1000,-15);
5052 addenemy(
5053 //ex,ey,
5054 x,y,
5055 dmisc3+0x1000,-15);
5056 //addenemy(ex,ey,dmisc3,0);
5057
5058 }
5059 item_set = 0; //Do not make a drop.
5060 hp = -1000;
5061 return -1;
5062
5063 }
5064 case edSUMMON:
5065 {
5066
5067
5068 //al_trace("edSplit dmisc3: %d\n", dmisc3);
5069 //al_trace("edSplit dmisc4: %d\n", dmisc4);
5070 int32_t summon_count = (zc_oldrand()%dmisc4)+1;
5071 for ( int32_t q = 0; q < summon_count; q++ )
5072 {
5073 int32_t x2=16*((zc_oldrand()%12)+2);
5074 int32_t y2=16*((zc_oldrand()%7)+2);
5075 addenemy(
5076 //(x+(txsz*16)/2),(y+(tysz*16)/2)
5077 x2,y2,
5078 dmisc3+0x1000,-15);
5079 //addenemy(ex,ey,dmisc3,0);
5080
5081 }
5082 sfx(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,pan(int32_t(x)));
5083 return -1;
5084
5085 }
5086
5087 case edEXPLODESMALL:
5088 {
5089 weapon *ew=new weapon(x,y-fakez,z, ewBomb, 0, dmisc4, dir,-1,getUID(),false);
5090 Ewpns.add(ew);
5091 item_set = 0; //Should we make a drop?
5092 hp = -1000;
5093 return -1;
5094 }
5095
5096
5097 case edEXPLODEHARMLESS:
5098 {
5099 weapon *ew=new weapon(x,y-fakez,z, ewSBomb, 0, dmisc4, dir,-1,getUID(),false);
5100 Ewpns.add(ew);
5101 ew->hyofs = -32768;
5102 item_set = 0; //Should we make a drop?
5103 hp = -1000;
5104 return -1;
5105 }
5106
5107
5108 case edEXPLODELARGE:
5109 {
5110 weapon *ew=new weapon(x,y-fakez,z, ewSBomb, 0, dmisc4, dir,-1,getUID(),false);
5111 Ewpns.add(ew);
5112
5113 hp = -1000;
5114 return -1;
5115 }
5116
5117
5118 case edTRIGGERSECRETS:
5119 {
5120 hidden_entrance(0, true, false, -4);
5121 return -1;
5122 }
5123
5124 case edSTUNORCHINK:
5125 if (stunclk && get_bit(quest_rules, qr_NO_STUNLOCK))
5126 {
5127 sfx(WAV_CHINK,pan(int32_t(x)));
5128 return 1;
5129 }
5130 else if(*power <= 0)
5131 {
5132 //al_trace("defendNew() is at: %s\n", "returning edSTUNORCHINK");
5133 sfx(WAV_CHINK,pan(int32_t(x)));
5134 return 1;
5135 }
5136 [[fallthrough]];
5137
5138 case edSTUNORIGNORE:
5139 if (stunclk && get_bit(quest_rules, qr_NO_STUNLOCK))
5140 {
5141 sfx(WAV_CHINK,pan(int32_t(x)));
5142 return 1;
5143 }
5144 else if(*power <= 0)
5145 return 0;
5146 [[fallthrough]];
5147
5148 case edSTUNONLY:
5149 if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wHookshot || wpnId==wSword) && stunclk>=159)
5150 {
5151 //al_trace("enemy::defend(), edSTUNONLY found a weapon of type FIRE, BOMB, SBOMB, HOOKSHOT, or SWORD:, with wpnId: \n", wpnId);
5152 // Z_message("enemy::defend(), edSTUNONLY found a weapon of type FIRE, BOMB, SBOMB, HOOKSHOT, or SWORD:, with wpnId: \n", wpnId);
5153 return 1;
5154 }
5155 if (stunclk && get_bit(quest_rules, qr_NO_STUNLOCK))
5156 {
5157 sfx(WAV_CHINK,pan(int32_t(x)));
5158 return 1;
5159 }
5160 else
5161 {
5162 stunclk=160;
5163 sfx(WAV_EHIT,pan(int32_t(x)));
5164
5165 return 1;
5166 }
5167
5168 case edCHINKL1:
5169 if(*power >= 1*game->get_hero_dmgmult()) break;
5170 [[fallthrough]];
5171 case edCHINKL2:
5172 if(*power >= 2*game->get_hero_dmgmult()) break;
5173 [[fallthrough]];
5174 case edCHINKL4:
5175 if(*power >= 4*game->get_hero_dmgmult()) break;
5176 [[fallthrough]];
5177 case edCHINKL6:
5178 if(*power >= 6*game->get_hero_dmgmult()) break;
5179 [[fallthrough]];
5180 case edCHINKL8:
5181 if(*power >= 8*game->get_hero_dmgmult()) break;
5182 [[fallthrough]];
5183 case edCHINKL10:
5184 if(*power >= 10*game->get_hero_dmgmult()) break;
5185 [[fallthrough]];
5186 case edCHINK:
5187 //al_trace("defendNew() is at: %s\n", "returning edCHINK");
5188 sfx(WAV_CHINK,pan(int32_t(x)));
5189 return 1;
5190
5191 case edIGNOREL1:
5192 if(*power > 0) break;
5193 [[fallthrough]];
5194
5195 case edIGNORE:
5196 return 0;
5197
5198 case ed1HKO:
5199 *power = hp;
5200 return -2;
5201
5202 case ed2x:
5203 {
5204 *power = zc_max(1,*power*2);
5205 //int32_t pow = *power;
5206 //*power = vbound((pow*2),0,214747);
5207 return -1;
5208 }
5209 case ed3x:
5210 {
5211 *power = zc_max(1,*power*3);
5212 //int32_t pow = *power;
5213 //*power = vbound((pow*3),0,214747);
5214 return -1;
5215 }
5216
5217 case ed4x:
5218 {
5219 *power = zc_max(1,*power*4);
5220 //int32_t pow = *power;
5221 //*power = vbound((pow*4),0,214747);
5222 return -1;
5223 }
5224
5225
5226 case edHEAL:
5227 { //Probably needs its own function, or routine in the damage functuon to heal if power is negative.
5228 //int32_t pow = *power;
5229 //*power = vbound((pow*-1),0,214747);
5230 //break;
5231 *power = zc_min(0,*power*-1);
5232 return -1;
5233 }
5234 /*
5235 case edLEVELDAMAGE:
5236 {
5237 int32_t pow = *power;
5238 int32_t lvl = *level;
5239 *power = vbound((pow*lvl),0,214747);
5240 break;
5241 }
5242 case edLEVELREDUCTION:
5243 {
5244 int32_t pow = *power;
5245 int32_t lvl = *level;
5246 *power = vbound((pow/lvl),0,214747);
5247 break;
5248 }
5249 */
5250
5251 case edQUARTDAMAGE:
5252 *power = zc_max(1,*power/2);
5253
5254 [[fallthrough]];
5255 case edHALFDAMAGE:
5256 *power = zc_max(1,*power/2);
5257 break;
5258
5259 case edSWITCH:
5260 {
5261 if(Hero.switchhookclk) return 0; //Already switching!
5262 switch(family)
5263 {
5264 case eeAQUA: case eeMOLD: case eeDONGO: case eeMANHAN: case eeGLEEOK:
5265 case eeDIG: case eeGHOMA: case eeLANM: case eePATRA: case eeGANON:
5266 return 0;
5267 }
5268 hooked_combopos = -1;
5269 hooked_layerbits = 0;
5270 switching_object = this;
5271 switch_hooked = true;
5272 Hero.doSwitchHook(game->get_switchhookstyle());
5273 if(QMisc.miscsfx[sfxSWITCHED])
5274 sfx(QMisc.miscsfx[sfxSWITCHED],int32_t(x));
5275 return 1;
5276 }
5277
5278 case 0:
5279 {
5280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(edef == edefSwitchHook)
5281 return -1;
5282
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 if (stunclk && get_bit(quest_rules, qr_NO_STUNLOCK) && *power == 0)
5283 {
5284 sfx(WAV_CHINK,pan(int32_t(x)));
5285 return 1;
5286 }
5287
5288 }
5289 7 }
5290
5291 7 return -1;
5292 7 }
5293
5294 7 int32_t enemy::defendNewInt(int32_t wpnId, int32_t *power, int32_t edef, byte unblockable, weapon* w)
5295 {
5296 7 std::vector<int32_t> &ev = FFCore.eventData;
5297 7 ev.clear();
5298 7 ev.push_back(*power*10000);
5299 7 ev.push_back(edef*10000);
5300 7 ev.push_back(unblockable*10000);
5301 7 ev.push_back(wpnId*10000);
5302 7 ev.push_back(0);
5303 7 ev.push_back(getUID());
5304
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 ev.push_back(w?w->getUID():0);
5305
5306 7 throwGenScriptEvent(GENSCR_EVENT_ENEMY_HIT1);
5307 7 *power = ev[0]/10000;
5308 7 edef = ev[1]/10000;
5309 7 unblockable = byte(ev[2]/10000);
5310 7 wpnId = ev[3] / 10000;
5311 7 bool nullify = ev[4]!=0;
5312 7 ev.clear();
5313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(nullify) return 0;
5314
5315 7 int32_t ret = defendNew(wpnId, power, edef, unblockable);
5316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(ret != -1) return ret;
5317 7 ev.push_back(*power*10000);
5318 7 ev.push_back(edef*10000);
5319 7 ev.push_back(unblockable*10000);
5320 7 ev.push_back(wpnId*10000);
5321 7 ev.push_back(0);
5322 7 ev.push_back(getUID());
5323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 ev.push_back(w?w->getUID():0);
5324
5325 7 throwGenScriptEvent(GENSCR_EVENT_ENEMY_HIT2);
5326 7 *power = ev[0]/10000;
5327 7 nullify = ev[4]!=0;
5328 7 ev.clear();
5329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(nullify) return 0;
5330 7 return -1;
5331 7 }
5332
5333 7 int32_t enemy::defenditemclassNew(int32_t wpnId, int32_t *power, weapon *w)
5334 {
5335 7 int32_t wid = getWeaponID(w);
5336
5337 7 int32_t edef = resolveEnemyDefence(w);
5338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(QHeader.zelda_version > 0x250)
5339 return defendNewInt(wid, power, edef, w->unblockable, w);
5340
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 switch(wid)
5341 {
5342 case wScript1: case wScript2: case wScript3: case wScript4: case wScript5:
5343 case wScript6: case wScript7: case wScript8: case wScript9: case wScript10:
5344 return defend(wpnId, power, edefSCRIPT);
5345
5346 case wWhistle:
5347 return -1;
5348
5349 default:
5350 7 return defendNewInt(wid, power, edef, w->unblockable, w);
5351 }
5352 7 }
5353
5354
5355 // Check defenses without actually acting on them.
5356 bool enemy::candamage(int32_t power, int32_t edef, byte unblockable)
5357 {
5358 switch(defense[edef])
5359 {
5360 case edSTUNONLY:
5361 return false;
5362 case edSTUNORCHINK:
5363 case edCHINK:
5364 return unblockable&WPNUNB_BLOCK;
5365 case edSTUNORIGNORE:
5366 case edIGNORE:
5367 return unblockable&WPNUNB_IGNR;
5368
5369 case edIGNOREL1:
5370 return (unblockable&WPNUNB_IGNR) || power >= 1*game->get_hero_dmgmult();
5371 case edCHINKL1:
5372 return (unblockable&WPNUNB_BLOCK) || power >= 1*game->get_hero_dmgmult();
5373
5374 case edCHINKL2:
5375 return (unblockable&WPNUNB_BLOCK) || power >= 2*game->get_hero_dmgmult();
5376
5377 case edCHINKL4:
5378 return (unblockable&WPNUNB_BLOCK) || power >= 4*game->get_hero_dmgmult();
5379
5380 case edCHINKL6:
5381 return (unblockable&WPNUNB_BLOCK) || power >= 6*game->get_hero_dmgmult();
5382
5383 case edCHINKL8:
5384 return (unblockable&WPNUNB_BLOCK) || power >= 8*game->get_hero_dmgmult();
5385 }
5386
5387 return true;
5388 }
5389
5390 // Do we do damage?
5391 // 0: takehit returns 0
5392 // 1: takehit returns 1
5393 // -1: do damage
5394 int32_t enemy::defend(int32_t wpnId, int32_t *power, int32_t edef)
5395 {
5396 if(shieldCanBlock)
5397 {
5398 switch(defense[edef])
5399 {
5400 case edIGNORE:
5401 return 0;
5402 case edIGNOREL1:
5403 case edSTUNORIGNORE:
5404 if(*power <= 0)
5405 return 0;
5406 }
5407
5408 sfx(WAV_CHINK,pan(int32_t(x)));
5409 return 1;
5410 }
5411
5412 switch(defense[edef])
5413 {
5414 case edSTUNORCHINK:
5415 if(*power <= 0)
5416 {
5417 sfx(WAV_CHINK,pan(int32_t(x)));
5418 return 1;
5419 }
5420
5421 [[fallthrough]];
5422 case edSTUNORIGNORE:
5423 if(*power <= 0)
5424 return 0;
5425
5426 [[fallthrough]];
5427 case edSTUNONLY:
5428 if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wHookshot || wpnId==wSword) && stunclk>=159)
5429 return 1;
5430
5431 stunclk=160;
5432 sfx(WAV_EHIT,pan(int32_t(x)));
5433 return 1;
5434
5435 case edFREEZE:
5436 frozenclock=-1;
5437 //sfx(WAV_FREEZE,pan(int32_t(x)));
5438 return 1;
5439
5440 case edCHINKL1:
5441 if(*power >= 1*game->get_hero_dmgmult()) break;
5442 [[fallthrough]];
5443 case edCHINKL2:
5444 if(*power >= 2*game->get_hero_dmgmult()) break;
5445 [[fallthrough]];
5446 case edCHINKL4:
5447 if(*power >= 4*game->get_hero_dmgmult()) break;
5448 [[fallthrough]];
5449 case edCHINKL6:
5450 if(*power >= 6*game->get_hero_dmgmult()) break;
5451 [[fallthrough]];
5452 case edCHINKL8:
5453 if(*power >= 8*game->get_hero_dmgmult()) break;
5454 [[fallthrough]];
5455 case edCHINKL10:
5456 if(*power >= 10*game->get_hero_dmgmult()) break;
5457 [[fallthrough]];
5458 case edCHINK:
5459 sfx(WAV_CHINK,pan(int32_t(x)));
5460 return 1;
5461 case edTRIGGERSECRETS:
5462 hidden_entrance(0, true, false, -4);
5463 break;
5464
5465 case edIGNOREL1:
5466 if(*power > 0) break;
5467 [[fallthrough]];
5468 case edIGNORE:
5469 return 0;
5470
5471 case ed1HKO:
5472 *power = hp;
5473 return -2;
5474
5475 case ed2x:
5476 {
5477 *power = zc_max(1,*power*2);
5478 //int32_t pow = *power;
5479 //*power = vbound((pow*2),0,214747);
5480 return -1;
5481 }
5482 case ed3x:
5483 {
5484 *power = zc_max(1,*power*3);
5485 //int32_t pow = *power;
5486 //*power = vbound((pow*3),0,214747);
5487 return -1;
5488 }
5489
5490 case ed4x:
5491 {
5492 *power = zc_max(1,*power*4);
5493 //int32_t pow = *power;
5494 //*power = vbound((pow*4),0,214747);
5495 return -1;
5496 }
5497
5498
5499 case edHEAL:
5500 { //Probably needs its own function, or routine in the damage functuon to heal if power is negative.
5501 //int32_t pow = *power;
5502 //*power = vbound((pow*-1),0,214747);
5503 //break;
5504 *power = zc_min(0,*power*-1);
5505 return -1;
5506 }
5507 /*
5508 case edLEVELDAMAGE:
5509 {
5510 int32_t pow = *power;
5511 int32_t lvl = *level;
5512 *power = vbound((pow*lvl),0,214747);
5513 break;
5514 }
5515 case edLEVELREDUCTION:
5516 {
5517 int32_t pow = *power;
5518 int32_t lvl = *level;
5519 *power = vbound((pow/lvl),0,214747);
5520 break;
5521 }
5522 */
5523
5524
5525 case edQUARTDAMAGE:
5526 *power = zc_max(1,*power/2);
5527
5528 [[fallthrough]];
5529 case edHALFDAMAGE:
5530 *power = zc_max(1,*power/2);
5531 break;
5532 }
5533
5534 return -1;
5535 }
5536
5537 // Defend against a particular item class.
5538 int32_t enemy::defenditemclass(int32_t wpnId, int32_t *power)
5539 {
5540 int32_t def=-1;
5541
5542 switch(wpnId)
5543 {
5544 // These first 2 are only used by Gohma... enemy::takehit() has complicated stun-calculation code for these.
5545 case wBrang:
5546 def = defend(wpnId, power, edefBRANG);
5547 break;
5548
5549 case wHookshot:
5550 def = defend(wpnId, power, edefHOOKSHOT);
5551 break;
5552
5553 // Anyway...
5554 case wBomb:
5555 def = defend(wpnId, power, edefBOMB);
5556 break;
5557
5558 case wSBomb:
5559 def = defend(wpnId, power, edefSBOMB);
5560 break;
5561
5562 case wArrow:
5563 def = defend(wpnId, power, edefARROW);
5564 break;
5565
5566 case wFire:
5567 def = defend(wpnId, power, edefFIRE);
5568 break;
5569
5570 case wWand:
5571 def = defend(wpnId, power, edefWAND);
5572 break;
5573
5574 case wMagic:
5575 def = defend(wpnId, power, edefMAGIC);
5576 break;
5577
5578 case wHammer:
5579 def = defend(wpnId, power, edefHAMMER);
5580 break;
5581
5582 case wSword:
5583 def = defend(wpnId, power, edefSWORD);
5584 break;
5585
5586 case wBeam:
5587 def = defend(wpnId, power, edefBEAM);
5588 break;
5589
5590 case wRefBeam:
5591 def = defend(wpnId, power, edefREFBEAM);
5592 break;
5593
5594 case wRefMagic:
5595 def = defend(wpnId, power, edefREFMAGIC);
5596 break;
5597
5598 case wRefFireball:
5599 def = defend(wpnId, power, edefREFBALL);
5600 break;
5601
5602 case wRefRock:
5603 def = defend(wpnId, power, edefREFROCK);
5604 break;
5605
5606 case wStomp:
5607 def = defend(wpnId, power, edefSTOMP);
5608 break;
5609
5610 case wCByrna:
5611 def = defend(wpnId, power, edefBYRNA);
5612 break;
5613
5614 case wScript1:
5615 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT01);
5616 else def = defend(wpnId, power, edefSCRIPT);
5617 break;
5618
5619 case wScript2:
5620 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT02);
5621 else def = defend(wpnId, power, edefSCRIPT);
5622 break;
5623
5624 case wScript3:
5625 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT03);
5626 else def = defend(wpnId, power, edefSCRIPT);
5627 break;
5628
5629 case wScript4:
5630 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT04);
5631 else def = defend(wpnId, power, edefSCRIPT);
5632 break;
5633
5634 case wScript5:
5635 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT05);
5636 else def = defend(wpnId, power, edefSCRIPT);
5637 break;
5638
5639 case wScript6:
5640 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT06);
5641 else def = defend(wpnId, power, edefSCRIPT);
5642 break;
5643
5644 case wScript7:
5645 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT07);
5646 else def = defend(wpnId, power, edefSCRIPT);
5647 break;
5648
5649 case wScript8:
5650 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT08);
5651 else def = defend(wpnId, power, edefSCRIPT);
5652 break;
5653
5654 case wScript9:
5655 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT09);
5656 else def = defend(wpnId, power, edefSCRIPT);
5657 break;
5658
5659 case wScript10:
5660 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefSCRIPT10);
5661 else def = defend(wpnId, power, edefSCRIPT);
5662 break;
5663
5664 case wWhistle:
5665 if(QHeader.zelda_version > 0x250) def = defend(wpnId, power, edefWhistle);
5666 else break;
5667 break;
5668
5669
5670 //!ZoriaRPG : We need some special cases here, to ensure that old script defs don;t break.
5671 //Probably best to do this from the qest file, loading the values of Script(generic) into each
5672 //of the ten if the quest version is lower than N.
5673 //Either that, or we need a boolean flag to set int32_t he enemy editor, or by ZScript that changes this behaviour.
5674 //such as bool UseSeparatedScriptDefences. hah.
5675 default:
5676 //if(wpnId>=wScript1 && wpnId<=wScript10)
5677 // {
5678 // def = defend(wpnId, power, edefSCRIPT);
5679 // }
5680 // }
5681
5682 break;
5683 }
5684
5685 return def;
5686 }
5687
5688 // take damage or ignore it
5689 // -1: damage (if any) dealt
5690 // 1: blocked
5691 // 0: weapon passes through unhindered
5692 7 int32_t enemy::takehit(weapon *w)
5693 {
5694
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if(fallclk||drownclk) return 0;
5695 7 int32_t wpnId = w->id;
5696 //al_trace("takehit() wpnId is %d\n",wpnId);
5697 //if ( wpnId == wWhistle ) al_trace("Whistle weapon in %s\n", "takehit");
5698 7 int32_t power = w->power;
5699 7 int32_t wpnx = w->x;
5700 7 int32_t wpny = w->y;
5701 7 int32_t enemyHitWeapon = w->parentitem;
5702 int32_t wpnDir;
5703 7 int32_t parent_item = w->parentitem;
5704
5705 //if ( parent_item > -1 )
5706 //{
5707 // if ( itemsbuf[parent_item].useweapon > 0 /*&& wpnId != wWhistle*/ )
5708 // {
5709 // wpnId = itemsbuf[parent_item].useweapon;
5710 // }
5711
5712 //}
5713 //if ( parent_item == -1 && w->ScriptGenerated )
5714 //{
5715 // if ( w->useweapon > 0 /*&& wpnId != wWhistle*/ )
5716 // {
5717 // wpnId = w->useweapon;
5718 // }
5719
5720 //}
5721 //al_trace("takehit wpnId is: %d\n",wpnId);
5722
5723 //Shoud be set from idata from the weapon::weaon constructor. -Z
5724
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if ( w->useweapon > 0 /*&& wpnId != wWhistle*/ )
5725 {
5726 wpnId = w->useweapon;
5727 }
5728
5729 //al_trace("takehit() useweapon is %d\n",itemsbuf[parent_item].useweapon);
5730
5731 //Weapon Editor -Z
5732
5733
5734 // If it's a boomerang that just bounced, use the opposite direction;
5735 // otherwise, it might bypass a shield. This probably won't handle
5736 // every case correctly, but it's better than having shields simply
5737 // not work against boomerangs.
5738
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 if(w->id==wBrang && w->misc==1 && w->clk2>=256 && w->clk2<264)
5739 wpnDir = oppositeDir[w->dir];
5740 else
5741 7 wpnDir = w->dir;
5742
5743
4/8
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
7 if(dying || clk<0 || hclk>0 || superman)
5744 {
5745 return 0;
5746 }
5747
5748 //Prevent boomerang from writing to hitby[] for more than one frame.
5749 //This also prevents stunlock.
5750 //if ( stunclk > 0 ) return 0;
5751 //this needs a rule for boomerangs that cannot stunlock!
5752 //further, bouncing weapons should probably SFX_CHINK and bounce here.
5753 //sigh.
5754
5755 7 int32_t ret = -1;
5756
5757 // This obscure quest rule...
5758
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 if(get_bit(quest_rules,qr_BOMBDARKNUTFIX) && (wpnId==wBomb || wpnId==wSBomb))
5759 {
5760 double _MSVC2022_tmp1, _MSVC2022_tmp2;
5761 double ddir=atan2_MSVC2022_FIX(double(wpny-y),double(x-wpnx));
5762 wpnDir=zc_oldrand()&3;
5763
5764 if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
5765 {
5766 wpnDir=down;
5767 }
5768 else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
5769 {
5770 wpnDir=right;
5771 }
5772 else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4)))
5773 {
5774 wpnDir=up;
5775 }
5776 else
5777 {
5778 wpnDir=left;
5779 }
5780 }
5781
5782 7 int32_t xdir = dir;
5783 7 shieldCanBlock=false;
5784
5785 //if (family==eeFLOAT && flags&(inv_front|inv_back_inv_left|inv_right)) xdir=down;
5786
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if(!(w->unblockable&WPNUNB_BLOCK)&&((wpnId==wHookshot && hitshield(wpnx, wpny, xdir))
5787
4/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
7 || ((flags&inv_front && wpnDir==(xdir^down)) || (flags&inv_back && wpnDir==(xdir^up)) || (flags&inv_left && wpnDir==(xdir^left)) || (flags&inv_right && wpnDir==(xdir^right))))
5788 )
5789 // The hammer should already be dealt with by subclasses (Walker etc.)
5790 {
5791 switch(wpnId)
5792 {
5793 // Weapons which shields protect against
5794 case wSword:
5795 case wWand:
5796 if(Hero.getCharging()>0)
5797 Hero.setAttackClk(Hero.getAttackClk()+1); //Cancel charging
5798
5799 [[fallthrough]];
5800 case wHookshot:
5801 case wHSHandle:
5802 case wBrang:
5803 shieldCanBlock=true;
5804 break;
5805
5806 case wBeam:
5807 case wRefBeam:
5808 // Mirror shielded enemies!
5809 #if 0
5810 if(false /*flags2&guy_mirror*/ && !get_bit(quest_rules,qr_SWORDMIRROR))
5811 {
5812 if(wpnId>wEnemyWeapons)
5813 return 0;
5814
5815 sfx(WAV_CHINK,pan(int32_t(x)));
5816 return 1;
5817 }
5818
5819 #endif
5820
5821 [[fallthrough]];
5822 case wRefRock:
5823 case wRefFireball:
5824 case wMagic:
5825 #if 0
5826 if(false /*flags2&guy_mirror*/ && (wpnId!=wRefRock || get_bit(quest_rules,qr_REFLECTROCKS)))
5827 {
5828 sfx(WAV_CHINK,pan(int32_t(x)));
5829 return 3;
5830 }
5831
5832 #endif
5833
5834 if(wpnId>wEnemyWeapons)
5835 return 0;
5836
5837 [[fallthrough]];
5838 default:
5839 shieldCanBlock=true;
5840 break;
5841
5842 // Bombs
5843 case wSBomb:
5844 case wBomb:
5845 if (!get_bit(quest_rules,qr_TRUEFIXEDBOMBSHIELD)) goto hitclock;
5846 else if (!get_bit(quest_rules,qr_BOMBSPIERCESHIELD))
5847 {
5848 sfx(WAV_CHINK,pan(int32_t(x)));
5849 return 0;
5850 }
5851 else break;
5852
5853 // Weapons which ignore shields
5854 case wWhistle:
5855 case wHammer:
5856 break;
5857
5858 // Weapons which shouldn't be removed by shields
5859 case wLitBomb:
5860 case wLitSBomb:
5861 case wWind:
5862 case wPhantom:
5863 case wSSparkle:
5864 case wBait:
5865 return 0;
5866
5867 [[fallthrough]];
5868 case wFire:
5869 #if 0
5870 if(false /*flags2&guy_mirror*/)
5871 {
5872 sfx(WAV_CHINK,pan(int32_t(x)));
5873 return 1;
5874 }
5875
5876 #endif
5877 ;
5878 }
5879 }
5880
5881
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 switch(wpnId)
5882 {
5883 case wWhistle: //No longer completely ignore whistle weapons! -Z
5884 {
5885
5886 if ( ((itemsbuf[parent_item].flags & ITEM_FLAG2) == 0) || ( parent_item == -1 ) ) //if the flag is set, or the weapon is scripted
5887 {
5888 //al_trace("Whistle weapon in %s\n", "takehit flag == 0");
5889 return 0; break;
5890 }
5891 else
5892 {
5893 w->power = power = itemsbuf[parent_item].misc5;
5894
5895 int32_t def = defendNewInt(wpnId, &power, resolveEnemyDefence(w), w->unblockable, w);
5896
5897 if(def <= 0)
5898 {
5899 if ( def == -2 ) hp -= hp;
5900 else hp -= power;
5901 return def;
5902 }
5903 break;
5904 }
5905 break;
5906 }
5907
5908 case wPhantom:
5909 return 0;
5910
5911 case wLitBomb:
5912 case wLitSBomb:
5913 case wBait:
5914 case wWind:
5915 case wSSparkle:
5916 return 0;
5917
5918 case wFSparkle:
5919
5920 // Only take sparkle damage if the sparkle's parent item is not
5921 // defended against.
5922 if(enemyHitWeapon > -1)
5923 {
5924 int32_t p = 0;
5925 int32_t f = itemsbuf[enemyHitWeapon].family;
5926
5927 switch(f)
5928 {
5929 case itype_arrow:
5930 if(!candamage(p, edefARROW, w->unblockable)) return 0;
5931
5932 break;
5933
5934 case itype_cbyrna:
5935 if(!candamage(p, edefBYRNA, w->unblockable)) return 0;
5936
5937 break;
5938
5939 case itype_brang:
5940 if(!candamage(p, edefBRANG, w->unblockable)) return 0;
5941
5942 break;
5943
5944 default:
5945 return 0;
5946 }
5947 }
5948
5949 wpnId = wSword;
5950 power = game->get_hero_dmgmult()>>1;
5951 goto fsparkle;
5952 break;
5953
5954 case wBrang:
5955 {
5956 //int32_t def = defendNew(wpnId, &power, edefBRANG, w);
5957 int32_t def = defendNewInt(wpnId, &power, resolveEnemyDefence(w), w->unblockable, w);
5958 //preventing stunlock might be best, here. -Z
5959 if(def >= 0) return def;
5960
5961 // Not hurt by 0-damage weapons
5962 if(!(flags & guy_bhit))
5963 {
5964 stunclk=160;
5965
5966 if(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))
5967 {
5968 hp -= (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))*game->get_hero_dmgmult();
5969 goto hitclock;
5970 }
5971
5972 break;
5973 }
5974
5975 if(!power)
5976 hp-=(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].fam_type : current_item(itype_brang))*game->get_hero_dmgmult();
5977 else
5978 hp-=power;
5979
5980 goto hitclock;
5981 }
5982
5983 case wHookshot:
5984 {
5985 //int32_t def = defendNew(wpnId, &power, edefHOOKSHOT,w);
5986 int32_t def = defendNewInt(wpnId, &power, resolveEnemyDefence(w), w->unblockable, w);
5987
5988 if(def >= 0) return def;
5989
5990 bool swgrab = switch_hooked || w->family_class == itype_switchhook;
5991 if(swgrab || !(flags & guy_bhit))
5992 {
5993 if(!swgrab)
5994 stunclk=160;
5995
5996 if(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot))
5997 {
5998 hp -= (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot))*game->get_hero_dmgmult();
5999 goto hitclock;
6000 }
6001
6002 break;
6003 }
6004
6005 if(!power) hp-=(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].fam_type : current_item(itype_hookshot))*game->get_hero_dmgmult();
6006 else
6007 hp-=power;
6008
6009 goto hitclock;
6010 }
6011 break;
6012
6013 case wHSHandle:
6014 {
6015 if(itemsbuf[enemyHitWeapon>-1 ? enemyHitWeapon : current_item_id(itype_hookshot)].flags & ITEM_FLAG1)
6016 return 0;
6017
6018 bool ignorehookshot = ((defense[edefHOOKSHOT] == edIGNORE) || ((defense[edefHOOKSHOT] == edIGNOREL1 || defense[edefHOOKSHOT] == edSTUNORIGNORE)
6019 && (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot)) <= 0));
6020
6021 // Peahats, Darknuts, Aquamentuses, Pols Voices, Wizzrobes, Manhandlas
6022 if(!(family==eePEAHAT || family==eeAQUA || family==eeMANHAN || (family==eeWIZZ && !ignorehookshot)
6023 || (family==eeWALK && dmisc9==e9tPOLSVOICE) || (family==eeWALK && flags&(inv_back|inv_front|inv_left|inv_right))))
6024 return 0;
6025
6026 power = game->get_hero_dmgmult();
6027 }
6028
6029 fsparkle:
6030
6031 [[fallthrough]];
6032 default:
6033 // Work out the defenses!
6034 {
6035 7 int32_t def = defenditemclassNew(wpnId, &power, w);
6036
6037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(def >= 0)
6038 return def;
6039
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 else if(def == -2)
6040 {
6041 ret = 0;
6042 }
6043 }
6044
6045
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
14 if(!power)
6046 {
6047 if(flags & guy_bhit)
6048 hp-=1;
6049 else
6050 {
6051 // Don't make a long chain of 'stun' hits
6052 if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wSword) && stunclk>0)
6053 return 1;
6054
6055
6056 if(!switch_hooked)
6057 stunclk=160;
6058 break;
6059 }
6060 }
6061 7 else hp-=power;
6062
6063 hitclock:
6064 7 hclk=33;
6065
6066 // Use w->dir instead of wpnDir to make sure boomerangs don't push enemies the wrong way
6067
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if((dir&2)==(w->dir&2))
6068 {
6069 4 sclk=(w->dir<<8)+16;
6070 4 }
6071 7 }
6072
6073
2/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 if(((wpnId==wBrang) || (get_bit(quest_rules,qr_NOFLASHDEATH))) && (hp<=0 && !immortal))
6074 {
6075 fading=fade_blue_poof;
6076 }
6077
6078
6079 /*
6080 if( hitsfx > 0 ) //user set hit sound.
6081 {
6082 if ( !dying ) //Don't play the hit sound when dying.
6083 sfx(hitsfx, pan(int32_t(x)));
6084 }
6085 else sfx(WAV_EHIT, pan(int32_t(x))); //Don't play this one if the user sets a custom sound!
6086 */
6087 /*
6088 if( hitsfx > 0 ) //A sound is set.
6089 {
6090 if ( !dying ) //Don't play the hit sound when dying.
6091 sfx(hitsfx, pan(int32_t(x)));
6092 }
6093 */
6094
3/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
7 if ( FFCore.getQuestHeaderInfo(vZelda) > 0x250 || ( FFCore.getQuestHeaderInfo(vZelda) == 0x250 && FFCore.getQuestHeaderInfo(vBuild) > 31 )) //2.53 Gamma 2 and later
6095 {
6096
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if( hitsfx > 0 ) //user-set hit sound.
6097 {
6098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!dying) //don't play the hit sound on death! -Z
6099 7 sfx(hitsfx, pan(int32_t(x)));
6100 7 }
6101 else sfx(WAV_EHIT, pan(int32_t(x))); //Don't play the hardcoded sound if the user sets a custom one.
6102 7 }
6103 else //2.50.2 or earlier
6104 {
6105 sfx(WAV_EHIT, pan(int32_t(x)));
6106 sfx(hitsfx, pan(int32_t(x)));
6107 }
6108
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(family==eeGUY)
6109 sfx(WAV_EDEAD, pan(int32_t(x)));
6110
6111 // Penetrating weapons
6112
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
7 if((wpnId==wArrow || wpnId==wBeam) && !cannotpenetrate())
6113 {
6114 6 int32_t item=enemyHitWeapon;
6115
6116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(wpnId==wArrow)
6117 {
6118 //If we use an arrow type for the item's Weapon type, the flags differ, so we need to rely on the flags from an arrow class.
6119 if(item>=0 && (itemsbuf[item].flags&ITEM_FLAG1) && (itemsbuf[parent_item].family == itype_arrow))
6120 return 0;
6121 else if(get_bit(quest_rules,qr_ARROWS_ALWAYS_PENETRATE)) return 0;
6122 //if(item<0)
6123 else
6124 item=current_item_id(itype_arrow);
6125 }
6126
6127 else
6128 {
6129
6130 //If we use an swordbeam type for the item's Weapon type, the flags differ, so we need to rely on the flags from an arrow class.
6131
2/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6 if(item>=0 && (itemsbuf[item].flags&ITEM_FLAG3) && (itemsbuf[parent_item].family == itype_sword))
6132 return 0;
6133
6134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 else if(get_bit(quest_rules,qr_SWORDBEAMS_ALWAYS_PENETRATE)) return 0;
6135 else
6136 //if(item<0)
6137 6 item=current_item_id(itype_sword);
6138 }
6139 6 }
6140
6141 7 return ret;
6142 7 }
6143
6144 3749 bool enemy::dont_draw()
6145 {
6146
3/6
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3749 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3749 times.
3749 if(fading==fade_invisible || (((flags2&guy_blinking)||(fading==fade_flicker)) && (clk&1)))
6147 return true;
6148
6149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
3749 if(flags&guy_invisible)
6150 return true;
6151
6152
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3749 if(flags&lens_only && !lensclk)
6153 return true;
6154
6155
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3749 if(lensclk && (itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG6) && !(itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG7) &&
6156 !((flags&lens_only) && (get_bit(quest_rules,qr_LENSSEESENEMIES) || (itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG5))))
6157 return true;
6158
6159 3749 return false;
6160 3749 }
6161
6162 #define DRAW_NORMAL 2
6163 #define DRAW_CLOAKED 1
6164 #define DRAW_INVIS 0
6165 // base drawing function to be used by all derived classes instead of
6166 // sprite::draw()
6167 3749 void enemy::draw(BITMAP *dest)
6168 {
6169
3/6
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3749 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3749 times.
3749 if(fading==fade_invisible || (((flags2&guy_blinking)||(fading==fade_flicker)) && (clk&1)))
6170 return;
6171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
3749 if(flags&guy_invisible)
6172 return;
6173
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3749 if(lensclk && (itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG6) && !(itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG7) && !(flags&lens_only))
6174 return;
6175
6176 //We did the normal don't_draw stuff here so we can make exceptions; specifically the lens check (which should make enemies
6177 // be cloaked if they have "invisible displays as cloaked" checked.
6178
6179 3749 byte canSee = DRAW_NORMAL;
6180 //Enemy specific stuff
6181
1/2
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
3749 if ( editorflags & ENEMY_FLAG1 )
6182 {
6183 canSee = DRAW_INVIS;
6184 if (editorflags & ENEMY_FLAG4) canSee = DRAW_CLOAKED;
6185 if (dmisc13 >= 0 && (editorflags & ENEMY_FLAG2))
6186 {
6187 if (game->item[dmisc13])
6188 {
6189 canSee = DRAW_NORMAL;
6190 }
6191 //else if ( lensclk && getlensid.flags SHOWINVIS )
6192 //{
6193 //
6194 //}
6195 //else
6196 //{
6197 // if ( (editorflags & ENEMY_FLAG4) ) canSee = DRAW_CLOAKED;
6198 // //otherwisem invisible
6199 //}
6200 }
6201 }
6202 //Room specific
6203
1/2
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
3749 if (tmpscr->flags3&fINVISROOM)
6204 {
6205 if (canSee == DRAW_NORMAL && !(current_item(itype_amulet)) &&
6206 !((itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG5) && lensclk) && family!=eeGANON) canSee = DRAW_CLOAKED;
6207 }
6208 //Lens check
6209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
3749 if (lensclk)
6210 {
6211 if((itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG6) && !(flags&lens_only))
6212 {
6213 if (canSee == DRAW_NORMAL)
6214 {
6215 if (itemsbuf[Hero.getLastLensID()].flags & ITEM_FLAG7) canSee = DRAW_CLOAKED;
6216 else canSee = DRAW_INVIS; //Should never happen cause dont_draw should catch this, but just in case.
6217 }
6218 }
6219 if(flags&lens_only)
6220 {
6221 if (canSee == DRAW_INVIS) canSee = DRAW_NORMAL;
6222 }
6223 }
6224 else
6225 {
6226
1/2
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
3749 if(flags&lens_only)
6227 canSee = DRAW_INVIS;
6228 }
6229
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3749 if (canSee == DRAW_INVIS && (editorflags & ENEMY_FLAG4)) canSee = DRAW_CLOAKED;
6230
2/4
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3749 times.
✗ Branch 3 not taken.
3749 if (canSee == DRAW_NORMAL && (editorflags & ENEMY_FLAG16)) canSee = DRAW_CLOAKED;
6231
6232
1/2
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
3749 if (canSee == DRAW_INVIS)
6233 return;
6234
6235
2/4
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3749 times.
3749 if(fallclk||drownclk)
6236 {
6237 if (canSee == DRAW_CLOAKED)
6238 {
6239 sprite::drawcloaked(dest);
6240 }
6241 else if (canSee == DRAW_NORMAL)
6242 {
6243 sprite::draw(dest);
6244 }
6245 return;
6246 }
6247 3749 int32_t cshold=cs;
6248
6249
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 3623 times.
3749 if(dying)
6250 {
6251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if(clk2>=19)
6252 {
6253 if(!(clk2&2))
6254 {
6255 //if the enemy isn't totally invisible, or if it is, but Hero has the item needed to reveal it, draw it.
6256 if (canSee == DRAW_CLOAKED)
6257 {
6258 sprite::drawcloaked(dest);
6259 }
6260 else if (canSee == DRAW_NORMAL)
6261 {
6262 sprite::draw(dest);
6263 }
6264 }
6265 return;
6266 }
6267
6268 126 flip = 0;
6269 126 tile = wpnsbuf[spr_death].tile;
6270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if ( do_animation )
6271 {
6272 126 int32_t offs = 0;
6273
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if(!get_bit(quest_rules,qr_HARDCODED_ENEMY_ANIMS))
6274 {
6275 if(clk2 > 2)
6276 {
6277 spr_death_anim_clk=0;
6278 clk2=1;
6279 if(hp > -1000)
6280 death_sfx();
6281 }
6282 if(clk2==1 && spr_death_anim_clk>-1)
6283 {
6284 ++clk2;
6285 spr_death_anim_frm=(spr_death_anim_clk/zc_max(wpnsbuf[spr_death].speed,1));
6286 spr_death_anim_frm *= zc_max(1,txsz);
6287 int32_t rows = TILEROW(tile+spr_death_anim_frm)-TILEROW(tile);
6288 spr_death_anim_frm += TILES_PER_ROW*(zc_min(0,tysz-1)*rows);
6289 if(++spr_death_anim_clk >= (zc_max(wpnsbuf[spr_death].speed,1) * zc_max(wpnsbuf[spr_death].frames,1)))
6290 {
6291 spr_death_anim_clk=-1;
6292 clk2=1;
6293 }
6294 }
6295 tile += spr_death_anim_frm;
6296 }
6297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 else if(BSZ)
6298 {
6299 offs = zc_min((15-clk2)/3,4);
6300 }
6301
4/4
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 42 times.
126 else if(clk2>6 && clk2<=12)
6302 {
6303 42 offs = 1;
6304 42 }
6305
6306
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 42 times.
126 if(offs)
6307 {
6308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 offs *= zc_max(1,txsz);
6309 42 int32_t rows = TILEROW(tile+offs)-TILEROW(tile);
6310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 offs += TILES_PER_ROW*(zc_min(0,tysz-1)*rows);
6311 42 }
6312 126 tile += offs;
6313 126 }
6314
6315
3/6
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 126 times.
126 if(!get_bit(quest_rules,qr_HARDCODED_ENEMY_ANIMS) || BSZ || fading==fade_blue_poof)
6316 cs = wpnsbuf[spr_death].csets&15;
6317 else
6318 126 cs = (((clk2+5)>>1)&3)+6;
6319 126 }
6320
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3616 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
3623 else if(hclk>0 && getCanFlicker())
6321 {
6322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(family==eeGANON)
6323 cs=(((hclk-1)>>1)&3)+6;
6324
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 else if(hclk<33 && !get_bit(quest_rules,qr_ENEMIESFLICKER))
6325 cs=(((hclk-1)>>1)&3)+6;
6326 7 }
6327 //draw every other frame for flickering enemies
6328
6/10
✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 1857 times.
✓ Branch 2 taken 1892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
✓ Branch 5 taken 1825 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 67 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
3749 if((frame&1)==1 || !(family !=eeGANON && hclk>0 && get_bit(quest_rules,qr_ENEMIESFLICKER) && getCanFlicker()))
6329 {
6330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
3749 if (canSee == DRAW_CLOAKED)
6331 {
6332 sprite::drawcloaked(dest);
6333 }
6334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
3749 else if (canSee == DRAW_NORMAL)
6335 {
6336
1/2
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
3749 if ( frozenclock < 0 )
6337 {
6338 if ( frozentile > 0 ) tile = frozentile;
6339 loadpalset(csBOSS,frozencset);
6340 }
6341 3749 sprite::draw(dest);
6342 3749 }
6343 3749 }
6344 3749 cs=cshold;
6345 3749 }
6346
6347 //old zc bosses
6348 3749 void enemy::drawzcboss(BITMAP *dest)
6349 {
6350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
3749 if(dont_draw())
6351 return;
6352
6353 3749 int32_t cshold=cs;
6354
6355
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 3623 times.
3749 if(dying)
6356 {
6357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if(clk2>=19)
6358 {
6359 if(!(clk2&2))
6360 sprite::drawzcboss(dest);
6361
6362 return;
6363 }
6364
6365 126 flip = 0;
6366 126 tile = wpnsbuf[spr_death].tile;
6367
6368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if ( do_animation )
6369 {
6370
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if(!get_bit(quest_rules,qr_HARDCODED_ENEMY_ANIMS))
6371 {
6372 if(clk2 > 2)
6373 {
6374 spr_death_anim_clk=0;
6375 clk2=1;
6376 if(hp > -1000)
6377 death_sfx();
6378 }
6379 if(clk2==1 && spr_death_anim_clk>-1)
6380 {
6381 ++clk2;
6382 spr_death_anim_frm=(spr_death_anim_clk/zc_max(wpnsbuf[spr_death].speed,1));
6383 spr_death_anim_frm *= zc_max(1,txsz);
6384 int32_t rows = TILEROW(tile+spr_death_anim_frm)-TILEROW(tile);
6385 spr_death_anim_frm += TILES_PER_ROW*(zc_min(0,tysz-1)*rows);
6386 if(++spr_death_anim_clk >= (zc_max(wpnsbuf[spr_death].speed,1) * zc_max(wpnsbuf[spr_death].frames,1)))
6387 {
6388 spr_death_anim_clk=-1;
6389 clk2=1;
6390 }
6391 }
6392 tile += spr_death_anim_frm;
6393 }
6394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 else if(BSZ)
6395 tile += zc_min((15-clk2)/3,4);
6396
4/4
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 42 times.
126 else if(clk2>6 && clk2<=12)
6397 42 ++tile;
6398 126 }
6399
6400
3/6
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 126 times.
126 if(!get_bit(quest_rules,qr_HARDCODED_ENEMY_ANIMS) || BSZ || fading==fade_blue_poof)
6401 cs = wpnsbuf[spr_death].csets&15;
6402 else
6403 126 cs = (((clk2+5)>>1)&3)+6;
6404 126 }
6405
2/2
✓ Branch 0 taken 3616 times.
✓ Branch 1 taken 7 times.
3623 else if(hclk>0)
6406 {
6407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(family==eeGANON)
6408 cs=(((hclk-1)>>1)&3)+6;
6409
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 else if(hclk<33 && !get_bit(quest_rules,qr_ENEMIESFLICKER))
6410 cs=(((hclk-1)>>1)&3)+6;
6411 7 }
6412
6413
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3749 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3749 if((tmpscr->flags3&fINVISROOM) &&
6414 !(current_item(itype_amulet)) &&
6415 !(get_bit(quest_rules,qr_LENSSEESENEMIES) &&
6416 lensclk) && family!=eeGANON)
6417 {
6418 sprite::drawcloaked(dest);
6419 }
6420 else
6421 {
6422
4/6
✓ Branch 0 taken 3749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
✓ Branch 3 taken 3616 times.
✓ Branch 4 taken 133 times.
✗ Branch 5 not taken.
3749 if(family !=eeGANON && hclk>0 && get_bit(quest_rules,qr_ENEMIESFLICKER))
6423 {
6424 if((frame&1)==1)
6425 sprite::drawzcboss(dest);
6426 }
6427 else
6428 3749 sprite::drawzcboss(dest);
6429 }
6430
6431 3749 cs=cshold;
6432 3749 }
6433
6434
6435 // similar to the overblock function--can do up to a 32x32 sprite
6436 //will this play nicely with scripttile, solely using the modifications in sprite::draw()?
6437 void enemy::drawblock(BITMAP *dest,int32_t mask)
6438 {
6439 int32_t thold=tile;
6440 int32_t t1=tile;
6441 int32_t t2=tile+20;
6442 int32_t t3=tile+1;
6443 int32_t t4=tile+21;
6444
6445 switch(mask)
6446 {
6447 case 1:
6448 enemy::drawzcboss(dest);
6449 break;
6450
6451 case 3:
6452 if(flip&2)
6453 zc_swap(t1,t2);
6454
6455 tile=t1;
6456 enemy::drawzcboss(dest);
6457 tile=t2;
6458 yofs+=16;
6459 enemy::drawzcboss(dest);
6460 yofs-=16;
6461 break;
6462
6463 case 5:
6464 t2=tile+1;
6465
6466 if(flip&1)
6467 zc_swap(t1,t2);
6468
6469 tile=t1;
6470 enemy::drawzcboss(dest);
6471 tile=t2;
6472 xofs+=16;
6473 enemy::drawzcboss(dest);
6474 xofs-=16;
6475 break;
6476
6477 case 15:
6478 if(flip&1)
6479 {
6480 zc_swap(t1,t3);
6481 zc_swap(t2,t4);
6482 }
6483
6484 if(flip&2)
6485 {
6486 zc_swap(t1,t2);
6487 zc_swap(t3,t4);
6488 }
6489
6490 tile=t1;
6491 enemy::drawzcboss(dest);
6492 tile=t2;
6493 yofs+=16;
6494 enemy::drawzcboss(dest);
6495 yofs-=16;
6496 tile=t3;
6497 xofs+=16;
6498 enemy::drawzcboss(dest);
6499 tile=t4;
6500 yofs+=16;
6501 enemy::drawzcboss(dest);
6502 xofs-=16;
6503 yofs-=16;
6504 break;
6505 }
6506
6507 tile=thold;
6508 }
6509
6510 void enemy::drawshadow(BITMAP *dest, bool translucent)
6511 {
6512 if(dont_draw() || isSideViewGravity())
6513 {
6514 return;
6515 }
6516
6517 if(dying)
6518 {
6519 return;
6520 }
6521
6522 if(((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))||
6523 (darkroom))
6524 {
6525 return;
6526 }
6527 else
6528 {
6529 if(enemycanfall(id, false) && shadowtile == 0)
6530 shadowtile = wpnsbuf[spr_shadow].tile;
6531
6532 if(z>0 || fakez>0 || !enemycanfall(id, false))
6533 {
6534 if(!shadow_overpit(this))
6535 sprite::drawshadow(dest,translucent);
6536 }
6537 }
6538 }
6539
6540 void enemy::masked_draw(BITMAP *dest,int32_t mx,int32_t my,int32_t mw,int32_t mh)
6541 {
6542 BITMAP *sub=create_sub_bitmap(dest,mx,my,mw,mh);
6543
6544 if(sub!=NULL)
6545 {
6546 xofs-=mx;
6547 yofs-=my;
6548 enemy::draw(sub);
6549 xofs+=mx;
6550 yofs+=my;
6551 destroy_bitmap(sub);
6552 }
6553 else
6554 enemy::draw(dest);
6555 }
6556
6557 // override hit detection to check for invicibility, stunned, etc
6558 bool enemy::hit(sprite *s)
6559 {
6560 if(!(s->scriptcoldet&1) || s->fallclk || s->drownclk) return false;
6561
6562 return (dying || hclk>0) ? false : sprite::hit(s);
6563 }
6564
6565 4121 bool enemy::hit(int32_t tx,int32_t ty,int32_t tz,int32_t txsz2,int32_t tysz2,int32_t tzsz2)
6566 {
6567
3/4
✓ Branch 0 taken 3977 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 3977 times.
✗ Branch 3 not taken.
4121 return (dying || hclk>0) ? false : sprite::hit(tx,ty,tz,txsz2,tysz2,tzsz2);
6568 }
6569 bool enemy::hit(int32_t tx,int32_t ty,int32_t txsz2,int32_t tysz2)
6570 {
6571 return (dying || hclk>0) ? false : sprite::hit(tx,ty,txsz2,tysz2);
6572 }
6573
6574 722 bool enemy::hit(weapon *w)
6575 {
6576
3/6
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 722 times.
722 if(!(w->scriptcoldet&1) || w->fallclk || w->drownclk) return false;
6577
6578
2/4
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
722 return (dying || hclk>0) ? false : sprite::hit(w);
6579 722 }
6580
6581 1303 bool enemy::can_pitfall(bool checkspawning)
6582 {
6583
2/4
✓ Branch 0 taken 1303 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1303 times.
✗ Branch 3 not taken.
1303 if((fading||isspawning)&&checkspawning) return false; //Don't fall during spawn.
6584
2/2
✓ Branch 0 taken 1300 times.
✓ Branch 1 taken 3 times.
1303 switch(guysbuf[id&0xFFF].family)
6585 {
6586 case eeAQUA:
6587 case eeDIG:
6588 case eeDONGO:
6589 case eeFAIRY:
6590 case eeGANON:
6591 case eeGHOMA:
6592 case eeGLEEOK:
6593 case eeGUY:
6594 case eeLANM:
6595 case eeMANHAN:
6596 case eeMOLD:
6597 case eeNONE:
6598 case eePATRA:
6599 case eeZORA:
6600 3 return false; //Disallowed types
6601 default:
6602 1300 return true;
6603 }
6604 1303 }
6605 //Handle death
6606 3650 void enemy::try_death(bool force_kill)
6607 {
6608
5/8
✓ Branch 0 taken 3650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3650 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 3643 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
3650 if(!dying && (force_kill || (hp<=0 && !immortal)))
6609 {
6610 7 std::vector<int32_t> &ev = FFCore.eventData;
6611 7 ev.clear();
6612 7 ev.push_back(10000);
6613 7 ev.push_back(getUID());
6614
6615 7 throwGenScriptEvent(GENSCR_EVENT_ENEMY_DEATH);
6616 7 bool isSaved = !ev[0];
6617 7 ev.clear();
6618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(isSaved) return;
6619
6620
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if(itemguy && (hasitem&2)!=0)
6621 {
6622 for(int32_t i=0; i<items.Count(); i++)
6623 {
6624 if(((item*)items.spr(i))->pickup&ipENEMY)
6625 {
6626 if (!get_bit(quest_rules, qr_BROKEN_ITEM_CARRYING))
6627 {
6628 if (get_bit(quest_rules, qr_ENEMY_DROPS_USE_HITOFFSETS))
6629 {
6630 items.spr(i)->x = x+hxofs+(hxsz/2)-8;
6631 items.spr(i)->y = y+hyofs+(hysz/2)-10-fakez;
6632 }
6633 else
6634 {
6635 if(extend >= 3)
6636 {
6637 items.spr(i)->x = x+(txsz-1)*8;
6638 items.spr(i)->y = y-2+(tysz-1)*8;
6639 }
6640 else
6641 {
6642 items.spr(i)->x = x;
6643 items.spr(i)->y = y - 2;
6644 }
6645 }
6646 items.spr(i)->z = z;
6647 items.spr(i)->fakez = fakez;
6648 }
6649 else
6650 {
6651 items.spr(i)->x = x;
6652 items.spr(i)->y = y - 2;
6653 }
6654 }
6655 }
6656 }
6657
6658 7 dying=true;
6659
6660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(fading==fade_flash_die)
6661 clk2=19+18*4;
6662 else
6663 {
6664 7 clk2 = BSZ ? 15 : 19;
6665
6666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(fading!=fade_blue_poof)
6667 7 fading=0;
6668 }
6669
6670
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(itemguy)
6671 {
6672 hasitem&=~2;
6673 item_set=0;
6674 }
6675
6676
3/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
7 if(currscr<128 && count_enemy && !script_spawned)
6677 7 game->guys[(currmap<<7)+currscr]-=1;
6678 7 }
6679 3650 }
6680
6681 // --==**==--
6682
6683 // Movement routines that can be used by derived classes as needed
6684
6685 // --==**==--
6686
6687 28 void enemy::fix_coords(bool bound)
6688 {
6689
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if ((get_bit(quest_rules,qr_OUTOFBOUNDSENEMIES) ? 1 : 0) ^ ((editorflags&ENEMY_FLAG11)?1:0)) return;
6690
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if(moveflags & FLAG_IGNORE_SCREENEDGE) bound = false;
6691
6692
6693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if(bound)
6694 {
6695
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if ( ((unsigned)(id&0xFFF)) < MAXGUYS )
6696 {
6697
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
28 x=vbound(x, 0, (( guysbuf[id].SIZEflags&guyflagOVERRIDE_TILE_WIDTH && !isflier(id) ) ? (256-((txsz-1)*16)) : 240));
6698
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
28 y=vbound(y, 0,(( guysbuf[id].SIZEflags&guyflagOVERRIDE_TILE_HEIGHT && !isflier(id) ) ? (176-((txsz-1)*16)) : 160));
6699 28 }
6700 else
6701 {
6702 x=vbound(x, 0,240);
6703 y=vbound(y, 0,160);
6704 }
6705 28 }
6706
6707
5/10
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 28 times.
28 if(!OUTOFBOUNDS)
6708 {
6709 /*x=((int32_t(x)&0xF0)+((int32_t(x)&8)?16:0));
6710
6711 if(isSideViewGravity())
6712 y=((int32_t(y)&0xF8)+((int32_t(y)&4)?8:0));
6713 else
6714 y=((int32_t(y)&0xF0)+((int32_t(y)&8)?16:0));
6715 */
6716 28 do_fix(x, 16, true);
6717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if(isSideViewGravity())
6718 do_fix(y,8,true);
6719 28 else do_fix(y,16,true);
6720 28 }
6721 28 }
6722 6 bool enemy::cannotpenetrate()
6723 {
6724
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 return (family == eeAQUA || family == eeMANHAN || family == eeGHOMA);
6725 }
6726
6727 bool enemy::canmove_old(int32_t ndir,zfix s,int32_t special,int32_t dx1,int32_t dy1,int32_t dx2,int32_t dy2)
6728 {
6729 bool ok;
6730 int32_t dx = 0, dy = 0;
6731 int32_t sv = 8;
6732
6733 //Why is this here??? Why is it needed???
6734 s += 0.5; // Make the ints round; doesn't seem to cause any problems.
6735
6736 switch(ndir)
6737 {
6738 case 8:
6739 case up:
6740 if(canfall(id) && isSideViewGravity())
6741 return false;
6742
6743 dy = dy1-s;
6744 special = (special==spw_clipbottomright)?spw_none:special;
6745 ok = !m_walkflag_old(x,y+dy,special, x, y) && !flyerblocked(x,y+dy, special);
6746 break;
6747
6748 case 12:
6749 case down:
6750 if(canfall(id) && isSideViewGravity())
6751 return false;
6752
6753 dy = dy2+s;
6754 ok = !m_walkflag_old(x,y+dy,special, x, y) && !flyerblocked(x,y+dy, special);
6755 break;
6756
6757 case 14:
6758 case left:
6759 dx = dx1-s;
6760 sv = ((isSideViewGravity())?7:8);
6761 special = (special==spw_clipbottomright||special==spw_clipright)?spw_none:special;
6762 ok = !m_walkflag_old(x+dx,y+sv,special, x, y) && !flyerblocked(x+dx,y+8, special);
6763 break;
6764
6765 case 10:
6766 case right:
6767 dx = dx2+s;
6768 sv = ((isSideViewGravity())?7:8);
6769 ok = !m_walkflag_old(x+dx,y+sv,special, x, y) && !flyerblocked(x+dx,y+8, special);
6770 break;
6771
6772 case 9:
6773 case r_up:
6774 dx = dx2+s;
6775 dy = dy1-s;
6776 ok = !m_walkflag_old(x,y+dy,special, x, y) && !m_walkflag_old(x+dx,y+sv,special, x, y) &&
6777 !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
6778 break;
6779
6780 case 11:
6781 case r_down:
6782 dx = dx2+s;
6783 dx = dy2+s;
6784 ok = !m_walkflag_old(x,y+dy,special, x, y) && !m_walkflag_old(x+dx,y+sv,special, x, y) &&
6785 !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
6786 break;
6787
6788 case 13:
6789 case l_down:
6790 dx = dx1-s;
6791 dy = dy2+s;
6792 ok = !m_walkflag_old(x,y+dy,special, x, y) && !m_walkflag_old(x+dx,y+sv,special, x, y) &&
6793 !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
6794 break;
6795
6796 case 15:
6797 case l_up:
6798 dx = dx1-s;
6799 dy = dy1-s;
6800 ok = !m_walkflag_old(x,y+dy,special, x, y) && !m_walkflag_old(x+dx,y+sv,special, x, y) &&
6801 !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
6802 break;
6803
6804 default:
6805 db=99;
6806 return true;
6807 }
6808
6809 return ok;
6810 }
6811
6812
6813
6814
6815 // returns true if next step is ok, false if there is something there
6816 54 bool enemy::canmove(int32_t ndir,zfix s,int32_t special,int32_t dx1,int32_t dy1,int32_t dx2,int32_t dy2, bool kb)
6817 {
6818 54 bool ok = false; //initialise the var, son't just declare it
6819 54 int32_t dx = 0, dy = 0;
6820 54 int32_t sv = 8;
6821 54 int32_t tries = 2; int32_t try_x = 0; int32_t try_y = 0;
6822 //Why is this here??? Why is it needed???
6823 54 s += 0.5; // Make the ints round; doesn't seem to cause any problems.
6824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 int32_t usexoffs = (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) ? hxofs : 0;
6825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 int32_t useyoffs = (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) ? hyofs : 0;
6826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 int32_t usewid = (SIZEflags&guyflagOVERRIDE_HIT_WIDTH) ? hxsz : 16;
6827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 int32_t usehei = (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) ? hysz : 16;
6828 54 bool offgrid = OFFGRID_ENEMY;
6829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if(!offgrid)
6830 {
6831 //Enemies smaller than 1-tile must act as 1-tile large, if off-grid movement is disabled.
6832
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if(usehei<16)usehei=16;
6833
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if(usewid<16)usewid=16;
6834 54 }
6835
4/9
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
54 switch(ndir) //need to check every 8 pixels between two points
6836 {
6837 case 8:
6838 case up:
6839 {
6840
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 if(enemycanfall(id) && isSideViewGravity())
6841 return false;
6842
6843 9 dy = dy1-s;
6844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 special = (special==spw_clipbottomright)?spw_none:special;
6845 9 tries = usewid/(offgrid ? 8 : 16);
6846 //Z_eventlog("Trying move UP, dy=%d,usewid=%d,usehei=%d\n",int32_t(dy),usewid,usehei);
6847
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9 times.
14 for ( ; tries > 0; --tries )
6848 {
6849
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
9 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy,special, ndir, x+usexoffs+try_x, y+useyoffs, kb) && !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy, special,kb);
6850 9 try_x += (offgrid ? 8 : 16);
6851
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (!ok) break;
6852 5 }
6853
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if(!ok) break;
6854
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if((usewid%16)>0) //Uneven width
6855 {
6856 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy,special, ndir, x+usexoffs+usewid-1, y+useyoffs, kb) && !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy, special,kb);
6857 }
6858 5 break;
6859 }
6860 case 12:
6861 case down:
6862 {
6863
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 if(enemycanfall(id) && isSideViewGravity())
6864 return false;
6865
6866 12 dy = dy2+s;
6867 12 tries = usewid/(offgrid ? 8 : 16);
6868 //Z_eventlog("Trying move DOWN, dy=%d,usewid=%d,usehei=%d\n",int32_t(dy),usewid,usehei);
6869
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 for ( ; tries > 0; --tries )
6870 {
6871
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
12 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy,special, ndir, x+usexoffs+try_x, y+useyoffs, kb) && !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+zc_max(usehei-16,0), special,kb);
6872 12 try_x += (offgrid ? 8 : 16);
6873
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (!ok) break;
6874 2 }
6875
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if(!ok) break;
6876
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if((usewid%16)>0) //Uneven width
6877 {
6878 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy,special, ndir, x+usexoffs+usewid-1, y+useyoffs, kb) && !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+zc_max(usehei-16,0), special,kb);
6879 }
6880 2 break;
6881 }
6882 case 14:
6883 case left:
6884 {
6885 26 dx = dx1-s;
6886 26 sv = ((isSideViewGravity())?7:0);
6887
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
26 special = (special==spw_clipbottomright||special==spw_clipright)?spw_none:special;
6888 26 tries = usehei/(offgrid ? 8 : 16);
6889 //Z_eventlog("Trying move LEFT, dx=%d,usewid=%d,usehei=%d\n",int32_t(dx),usewid,usehei);
6890
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 26 times.
44 for ( ; tries > 0; --tries )
6891 {
6892
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 18 times.
26 ok = !m_walkflag(x+usexoffs+dx,y+useyoffs+try_y+sv,special, ndir, x+usexoffs, y+useyoffs+try_y, kb) && !flyerblocked(x+usexoffs+dx,y+8+useyoffs+try_y, special,kb);
6893 26 try_y += (offgrid ? 8 : 16);
6894
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 8 times.
26 if (!ok) break;
6895 18 }
6896
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 8 times.
26 if(!ok) break;
6897
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if((usehei%16)>0) //Uneven height
6898 {
6899 ok = !m_walkflag(x+usexoffs+dx,y+useyoffs+usehei-1+sv,special, ndir, x+usexoffs, y+useyoffs+usehei-1, kb) && !flyerblocked(x+usexoffs+dx,y+8+useyoffs+usehei-1, special,kb);
6900 }
6901 18 break;
6902 }
6903 case 10:
6904 case right:
6905 {
6906 7 dx = dx2+s;
6907 7 sv = ((isSideViewGravity())?7:0);
6908 7 tries = usehei/(offgrid ? 8 : 16);
6909 //Z_eventlog("Trying move RIGHT, dx=%d,usewid=%d,usehei=%d\n",int32_t(dx),usewid,usehei);
6910
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 for ( ; tries > 0; --tries )
6911 {
6912
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
7 ok = !m_walkflag(x+usexoffs+dx,y+useyoffs+try_y+sv,special, ndir, x+usexoffs, y+useyoffs+try_y, kb) && !flyerblocked(x+usexoffs+dx+zc_max(usewid-16,0),y+8+useyoffs+try_y, special,kb);
6913 7 try_y += (offgrid ? 8 : 16);
6914
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (!ok) break;
6915 3 }
6916
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if(!ok) break;
6917
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if((usehei%16)>0) //Uneven height
6918 {
6919 ok = !m_walkflag(x+usexoffs+dx,y+useyoffs+usehei-1+sv,special, ndir, x+usexoffs, y+useyoffs+usehei-1, kb) && !flyerblocked(x+usexoffs+dx+zc_max(usewid-16,0),y+8+useyoffs+usehei-1, special,kb);
6920 }
6921 3 break;
6922 }
6923 case 9:
6924 case r_up:
6925 {
6926 dx = dx2+s;
6927 dy = dy1-s;
6928 int32_t tries_x = usewid/(offgrid ? 8 : 16);
6929 sv = ((isSideViewGravity())?7:0);
6930 for ( ; tries_x > 0; --tries_x )
6931 {
6932 int32_t tries_y = usehei/(offgrid ? 8 : 16);
6933 try_y = 0;
6934 for ( ; tries_y > 0; --tries_y )
6935 {
6936 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) &&
6937 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+try_y, special,kb);
6938 try_y += (offgrid ? 8 : 16);
6939 if (!ok) break;
6940 }
6941 if (!ok) break;
6942 if((usehei%16)>0) //Uneven height
6943 {
6944 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) &&
6945 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+usehei-1, special,kb);
6946 }
6947 try_x += (offgrid ? 8 : 16);
6948 }
6949 if(!ok) break;
6950 if((usewid%16)>0) //Uneven width
6951 {
6952 int32_t tries_y = usehei/(offgrid ? 8 : 16);
6953 try_y = 0;
6954 for ( ; tries_y > 0; --tries_y )
6955 {
6956 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) &&
6957 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+try_y, special,kb);
6958 try_y += (offgrid ? 8 : 16);
6959 if (!ok) break;
6960 }
6961 if (!ok) break;
6962 if((usehei%16)>0) //Uneven height
6963 {
6964 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) &&
6965 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+usehei-1, special,kb);
6966 }
6967 }
6968 break;
6969 }
6970 case 11:
6971 case r_down:
6972 {
6973 dx = dx2+s;
6974 dx = dy2+s;
6975 int32_t tries_x = usewid/(offgrid ? 8 : 16);
6976 //sv = ((isSideViewGravity())?7:0);
6977 for ( ; tries_x > 0; --tries_x )
6978 {
6979 int32_t tries_y = usehei/(offgrid ? 8 : 16);
6980 try_y = 0;
6981 for ( ; tries_y > 0; --tries_y )
6982 {
6983 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) &&
6984 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+try_y, special,kb);
6985 try_y += (offgrid ? 8 : 16);
6986 if (!ok) break;
6987 }
6988 if (!ok) break;
6989 if((usehei%16)>0) //Uneven height
6990 {
6991 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) &&
6992 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+usehei-1, special,kb);
6993 }
6994 try_x += (offgrid ? 8 : 16);
6995 }
6996 if(!ok) break;
6997 if((usewid%16)>0) //Uneven width
6998 {
6999 int32_t tries_y = usehei/(offgrid ? 8 : 16);
7000 try_y = 0;
7001 for ( ; tries_y > 0; --tries_y )
7002 {
7003 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) &&
7004 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+try_y, special,kb);
7005 try_y += (offgrid ? 8 : 16);
7006 if (!ok) break;
7007 }
7008 if (!ok) break;
7009 if((usehei%16)>0) //Uneven height
7010 {
7011 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) &&
7012 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+usehei-1, special,kb);
7013 }
7014 }
7015 break;
7016 }
7017 case 13:
7018 case l_down:
7019 {
7020 dx = dx1-s;
7021 dy = dy2+s;
7022 int32_t tries_x = usewid/(offgrid ? 8 : 16);
7023 //sv = ((isSideViewGravity())?7:0);
7024 for ( ; tries_x > 0; --tries_x )
7025 {
7026 int32_t tries_y = usehei/(offgrid ? 8 : 16);
7027 try_y = 0;
7028 for ( ; tries_y > 0; --tries_y )
7029 {
7030 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) &&
7031 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+try_y, special,kb);
7032 try_y += (offgrid ? 8 : 16);
7033 if (!ok) break;
7034 }
7035 if (!ok) break;
7036 if((usehei%16)>0) //Uneven height
7037 {
7038 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) &&
7039 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+usehei-1, special,kb);
7040 }
7041 try_x += (offgrid ? 8 : 16);
7042 }
7043 if(!ok) break;
7044 if((usewid%16)>0) //Uneven width
7045 {
7046 int32_t tries_y = usehei/(offgrid ? 8 : 16);
7047 try_y = 0;
7048 for ( ; tries_y > 0; --tries_y )
7049 {
7050 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) &&
7051 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+try_y, special,kb);
7052 try_y += (offgrid ? 8 : 16);
7053 if (!ok) break;
7054 }
7055 if (!ok) break;
7056 if((usehei%16)>0) //Uneven height
7057 {
7058 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) &&
7059 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+usehei-1, special,kb);
7060 }
7061 }
7062 break;
7063 }
7064 case 15:
7065 case l_up:
7066 {
7067 dx = dx1-s;
7068 dy = dy1-s;
7069 int32_t tries_x = usewid/(offgrid ? 8 : 16);
7070 sv = ((isSideViewGravity())?7:0);
7071 for ( ; tries_x > 0; --tries_x )
7072 {
7073 int32_t tries_y = usehei/(offgrid ? 8 : 16);
7074 try_y = 0;
7075 for ( ; tries_y > 0; --tries_y )
7076 {
7077 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+try_x, y+useyoffs+try_y, kb) &&
7078 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+try_y, special,kb);
7079 try_y += (offgrid ? 8 : 16);
7080 if (!ok) break;
7081 }
7082 if (!ok) break;
7083 if((usehei%16)>0) //Uneven height
7084 {
7085 ok = !m_walkflag(x+usexoffs+try_x,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+try_x,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+try_x, y+useyoffs+usehei-1, kb) &&
7086 !flyerblocked(x+usexoffs+try_x,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+try_x,y+useyoffs+8+usehei-1, special,kb);
7087 }
7088 try_x += (offgrid ? 8 : 16);
7089 }
7090 if(!ok) break;
7091 if((usewid%16)>0) //Uneven width
7092 {
7093 int32_t tries_y = usehei/(offgrid ? 8 : 16);
7094 try_y = 0;
7095 for ( ; tries_y > 0; --tries_y )
7096 {
7097 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+try_y,special,ndir, x+usexoffs+usewid-1, y+useyoffs+try_y, kb) &&
7098 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+try_y, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+try_y, special,kb);
7099 try_y += (offgrid ? 8 : 16);
7100 if (!ok) break;
7101 }
7102 if (!ok) break;
7103 if((usehei%16)>0) //Uneven height
7104 {
7105 ok = !m_walkflag(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) && !m_walkflag(x+usexoffs+dx+usewid-1,y+useyoffs+sv+usehei-1,special,ndir, x+usexoffs+usewid-1, y+useyoffs+usehei-1, kb) &&
7106 !flyerblocked(x+usexoffs+usewid-1,y+useyoffs+dy+usehei-1, special,kb) && !flyerblocked(x+usexoffs+dx+usewid-1,y+useyoffs+8+usehei-1, special,kb);
7107 }
7108 }
7109 break;
7110 }
7111 default:
7112 db=99;
7113 return true;
7114 }
7115 //Z_eventlog("\n");
7116 54 return ok;
7117 54 }
7118
7119
7120 bool enemy::canmove(int32_t ndir,zfix s,int32_t special, bool kb)
7121 {
7122 int32_t usewid = (SIZEflags&guyflagOVERRIDE_HIT_WIDTH) ? hxsz : 16;
7123 int32_t usehei = (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) ? hysz : 16;
7124 if (usewid % 16 != 0) usewid += (16 - (usewid%16));
7125 if (usehei % 16 != 0) usehei += (16 - (usehei%16));
7126 --usewid;
7127 --usehei;
7128 return canmove(ndir,s,special,0,-8,usewid,usehei,kb);
7129 }
7130
7131 54 bool enemy::canmove(int32_t ndir,int32_t special, bool kb)
7132 {
7133 54 bool dodongo_move=true; //yes, it's an ugly hack, but we're going to rewrite everything later anyway - DN
7134
7135
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
54 if(special==spw_clipright&&ndir==right)
7136 {
7137 dodongo_move=canmove(ndir,(zfix)1,special,0,-8,31,15,kb);
7138 }
7139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 int32_t usewid = (SIZEflags&guyflagOVERRIDE_HIT_WIDTH) ? hxsz : 16;
7140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 int32_t usehei = (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) ? hysz : 16;
7141
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if (usewid % 16 != 0) usewid += (16 - (usewid%16));
7142
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if (usehei % 16 != 0) usehei += (16 - (usehei%16));
7143 54 --usewid;
7144 54 --usehei;
7145
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 28 times.
54 return canmove(ndir,(zfix)1,special,0,-8,usewid,usehei,kb)&&dodongo_move;
7146 }
7147
7148 bool enemy::canmove(int32_t ndir, bool kb)
7149 {
7150 return canmove(ndir,(zfix)1,spw_none,0,-8,15,15,kb);
7151 }
7152
7153 // 8-directional
7154 void enemy::newdir_8_old(int32_t newrate,int32_t newhoming,int32_t special,int32_t dx1,int32_t dy1,int32_t dx2,int32_t dy2)
7155 {
7156 int32_t ndir=0;
7157
7158 // can move straight, check if it wants to turn
7159 if(canmove_old(dir,step,special,dx1,dy1,dx2,dy2))
7160 {
7161 if(grumble && (zc_oldrand()&4)<grumble) //Homing
7162 {
7163 int32_t w = Lwpns.idFirst(wBait);
7164
7165 if(w>=0)
7166 {
7167 int32_t bx = Lwpns.spr(w)->x;
7168 int32_t by = Lwpns.spr(w)->y;
7169
7170 ndir = (bx<x) ? left : (bx!=x) ? right : 0;
7171
7172 if(abs(int32_t(y)-by)>14)
7173 {
7174 if(ndir>0) // Already left or right
7175 {
7176 // Making the diagonal directions
7177 ndir += (by<y) ? 2 : 4;
7178 }
7179 else
7180 {
7181 ndir = (by<y) ? up : down;
7182 }
7183 }
7184
7185 if(canmove(ndir,special,false))
7186 {
7187 dir=ndir;
7188 return;
7189 }
7190 }
7191 }
7192
7193 // Homing added.
7194 if(newhoming && (zc_oldrand()&255)<newhoming)
7195 {
7196 ndir = lined_up(8,true);
7197
7198 if(ndir>=0 && canmove(ndir,special,false))
7199 {
7200 dir=ndir;
7201 }
7202
7203 return;
7204 }
7205
7206 int32_t r=zc_oldrand();
7207
7208 if(newrate>0 && !(r%newrate))
7209 {
7210 ndir = ((dir+((r&64)?-1:1))&7)+8;
7211 int32_t ndir2=((dir+((r&64)?1:-1))&7)+8;
7212
7213 if(canmove(ndir,step,special,dx1,dy1,dx2,dy2,false))
7214 dir=ndir;
7215 else if(canmove(ndir2,step,special,dx1,dy1,dx2,dy2,false))
7216 dir=ndir2;
7217
7218 if(dir==ndir && (newrate>=4)) // newrate>=4, otherwise movement is biased toward upper-left
7219 // due to numerous lost fractional components. -L
7220 {
7221 x.doFloor();
7222 y.doFloor();
7223 }
7224 }
7225
7226 return;
7227 }
7228
7229 // can't move straight, must turn
7230 int32_t i=0;
7231
7232 for(; i<32; i++) // Try random dir
7233 {
7234 ndir=(zc_oldrand()&7)+8;
7235
7236 if(canmove(ndir,step,special,dx1,dy1,dx2,dy2,false))
7237 break;
7238 }
7239
7240 if(i==32)
7241 {
7242 for(ndir=8; ndir<16; ndir++)
7243 {
7244 if(canmove(ndir,step,special,dx1,dy1,dx2,dy2,false))
7245 goto ok;
7246 }
7247
7248 ndir = (isSideViewGravity()) ? (zc_oldrand()&1 ? left : right) : -1; // Sideview enemies get trapped if their dir becomes -1
7249 }
7250
7251 ok:
7252 dir=ndir;
7253 x.doFloor();
7254 y.doFloor();
7255 }
7256
7257 void enemy::newdir_8(int32_t newrate,int32_t newhoming,int32_t special,int32_t dx1,int32_t dy1,int32_t dx2,int32_t dy2)
7258 {
7259 int32_t ndir=0;
7260
7261 // can move straight, check if it wants to turn
7262 if(canmove(dir,step,special,dx1,dy1,dx2,dy2,false))
7263 {
7264 if(grumble && (zc_oldrand()&4)<abs(grumble)) //Homing
7265 {
7266 int32_t i = Lwpns.idFirst(wBait);
7267 if(i >= 0) //idfirst returns -1 if it can't find any
7268 {
7269 weapon *w = (weapon*)Lwpns.spr(i);
7270 if (get_bit(quest_rules, qr_FIND_CLOSEST_BAIT))
7271 {
7272 int32_t currentrange;
7273 if (distance(x, y, w->x, w->y) < w->misc2 || w->misc2 == 0) currentrange = distance(x, y, w->x, w->y);
7274 else currentrange = -1;
7275 int curid = i;
7276 ++i; //increment beforehand cause we just checked the first bait weapon and all others must be after it. ...otherwise it wouldn't be the first. -Deedee
7277 for(; i<Lwpns.Count(); ++i)
7278 {
7279 weapon *lw = (weapon*)Lwpns.spr(i);
7280 if (lw->id == wBait && distance(x, y, lw->x, lw->y) < currentrange && (distance(x, y, lw->x, lw->y) < lw->misc2 || lw->misc2 == 0))
7281 {
7282 currentrange = distance(x, y, lw->x, lw->y);
7283 curid = i;
7284 }
7285 }
7286 i = curid;
7287 if (currentrange == -1) i = -1;
7288 }
7289 else
7290 {
7291 if (!(distance(x, y, w->x, w->y) < w->misc2 || w->misc2 == 0)) i = -1;
7292 }
7293 if(i>=0)
7294 {
7295 int32_t bx = Lwpns.spr(i)->x;
7296 int32_t by = Lwpns.spr(i)->y;
7297
7298 ndir = (bx<x) ? left : (bx!=x) ? right : 0;
7299
7300 if(abs(int32_t(y)-by)>14)
7301 {
7302 if(ndir>0) // Already left or right
7303 {
7304 // Making the diagonal directions
7305 ndir += (by<y) ? 2 : 4;
7306 }
7307 else
7308 {
7309 ndir = (by<y) ? up : down;
7310 }
7311 }
7312 if (grumble < 0 || (itemsbuf[((weapon*)Lwpns.spr(i))->parentitem].flags & ITEM_FLAG1)) ndir = oppositeDir[ndir];
7313 if(canmove(ndir,special,false))
7314 {
7315 dir=ndir;
7316 return;
7317 }
7318 }
7319 }
7320 }
7321
7322 // Homing added.
7323 if(newhoming && (zc_oldrand()&255)<abs(newhoming))
7324 {
7325 ndir = lined_up(8,true);
7326 if (newhoming < 0 && ndir >= 0) ndir = oppositeDir[ndir];
7327 if(ndir>=0 && canmove(ndir,special,false))
7328 {
7329 dir=ndir;
7330 }
7331
7332 return;
7333 }
7334
7335 int32_t r=zc_oldrand();
7336
7337 if(newrate>0 && !(r%newrate))
7338 {
7339 ndir = ((dir+((r&64)?-1:1))&7)+8;
7340 int32_t ndir2=((dir+((r&64)?1:-1))&7)+8;
7341
7342 if(canmove(ndir,step,special,dx1,dy1,dx2,dy2,false))
7343 dir=ndir;
7344 else if(canmove(ndir2,step,special,dx1,dy1,dx2,dy2,false))
7345 dir=ndir2;
7346
7347 if(dir==ndir && (newrate>=4)) // newrate>=4, otherwise movement is biased toward upper-left
7348 // due to numerous lost fractional components. -L
7349 {
7350 x.doFloor();
7351 y.doFloor();
7352 }
7353 }
7354
7355 return;
7356 }
7357
7358 // can't move straight, must turn
7359 int32_t i=0;
7360
7361 for(; i<32; i++) // Try random dir
7362 {
7363 ndir=(zc_oldrand()&7)+8;
7364
7365 if(canmove(ndir,step,special,dx1,dy1,dx2,dy2,false))
7366 break;
7367 }
7368
7369 if(i==32)
7370 {
7371 for(ndir=8; ndir<16; ndir++)
7372 {
7373 if(canmove(ndir,step,special,dx1,dy1,dx2,dy2,false))
7374 goto ok;
7375 }
7376
7377 ndir = (isSideViewGravity()) ? (zc_oldrand()&1 ? left : right) : -1; // Sideview enemies get trapped if their dir becomes -1
7378 }
7379
7380 ok:
7381 dir=ndir;
7382 x.doFloor();
7383 y.doFloor();
7384 }
7385
7386 void enemy::newdir_8(int32_t newrate,int32_t newhoming,int32_t special)
7387 {
7388 newdir_8(newrate,newhoming,special,0,-8,15,15);
7389 }
7390
7391 void enemy::newdir_8_old(int32_t newrate,int32_t newhoming,int32_t special)
7392 {
7393 newdir_8_old(newrate,newhoming,special,0,-8,15,15);
7394 }
7395
7396 // makes the enemy slide backwards when hit
7397 // sclk: first byte is clk, second byte is dir
7398 // makes the enemy slide backwards when hit
7399 // sclk: first byte is clk, second byte is dir
7400 1138 int32_t enemy::slide()
7401 {
7402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1138 times.
1138 if(script_knockback_clk!=0) //scripted knockback
7403 {
7404 sclk = 0;
7405 return 1; //scripted knockback ran
7406 }
7407
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1135 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
1138 if(sclk==0 || (hp<=0 && !immortal))
7408 1138 return 0;
7409
7410 if(knockbackflags & FLAG_NOSLIDE)
7411 {
7412 sclk = 0;
7413 if(!OFFGRID_ENEMY)
7414 {
7415 //Fix to grid
7416 //x = (int32_t(x)+8)-((int32_t(x)+8)%16);
7417 //y = (int32_t(y)+8)-((int32_t(y)+8)%16);
7418 do_fix(x, 16, true);
7419 do_fix(y, 16, true);
7420 }
7421 return 0;
7422 }
7423 if((sclk&255)==16 && (get_bit(quest_rules,qr_OLD_ENEMY_KNOCKBACK_COLLISION) || knockbackSpeed!=4 ? !canmove(sclk>>8,(zfix) (dmisc2==e2tSPLITHIT ? 1 : 12),0,true) : !canmove(sclk>>8,(zfix) (dmisc2==e2tSPLITHIT ? 1 : knockbackSpeed),0,0,0,15,15,true)))
7424 {
7425 sclk=0;
7426 return 0;
7427 }
7428
7429 --sclk;
7430
7431 switch(sclk>>8)
7432 {
7433 case up:
7434 {
7435 if(y<=(dmisc2==e2tSPLITHIT ? 0 : (get_bit(quest_rules,qr_OLD_ENEMY_KNOCKBACK_COLLISION)?16:0))) //vires
7436 {
7437 sclk=0;
7438 return 0;
7439 }
7440 if ( dmisc2==e2tSPLITHIT && !canmove(sclk>>8,(zfix)(4),0,true) ) { sclk=0; return 0; } //vires
7441
7442 break;
7443 }
7444 case down:
7445 {
7446 if(y>=(dmisc2==e2tSPLITHIT ? 150 : 160)) //was 160 --changed for vires bug.
7447 {
7448 sclk=0;
7449 return 0;
7450 }
7451 if ( dmisc2==e2tSPLITHIT && !canmove(sclk>>8,(zfix)(4),0,true) ) { sclk=0; return 0; } //vires
7452
7453 break;
7454 }
7455 case left:
7456 {
7457 if(x<=(dmisc2==e2tSPLITHIT ? 0 : (get_bit(quest_rules,qr_OLD_ENEMY_KNOCKBACK_COLLISION)?16:0)))
7458 {
7459 sclk=0;
7460 return 0;
7461 }
7462 if ( dmisc2==e2tSPLITHIT && !canmove(sclk>>8,(zfix)(4),0,true) ) { sclk=0; return 0; }
7463
7464 break;
7465 }
7466 case right:
7467 {
7468 if(x>=(dmisc2==e2tSPLITHIT ? 255 : 240)) //vires
7469 {
7470 sclk=0;
7471 return 0;
7472 }
7473 if ( dmisc2==e2tSPLITHIT && !canmove(sclk>>8,(zfix)(4),0,true) ) { sclk=0; return 0; } //vires
7474 break;
7475 }
7476 }
7477
7478 int32_t move = knockbackSpeed;
7479 while(move>0)
7480 {
7481 int32_t thismove = zc_min(8, move);
7482 move -= thismove;
7483 hitdir = (sclk>>8);
7484 switch(sclk>>8)
7485 {
7486 case up:
7487 y-=thismove;
7488 break;
7489
7490 case down:
7491 y+=thismove;
7492 break;
7493
7494 case left:
7495 x-=thismove;
7496 break;
7497
7498 case right:
7499 x+=thismove;
7500 break;
7501 }
7502 if(!canmove(sclk>>8,(zfix)0,0,true))
7503 {
7504 switch(sclk>>8)
7505 {
7506 case up:
7507 case down:
7508 if(y < 0)
7509 y = 0;
7510 else if((int32_t(y)&15) > 7)
7511 y=(int32_t(y)&0xF0)+16;
7512 else
7513 y=(int32_t(y)&0xF0);
7514
7515 break;
7516
7517 case left:
7518 case right:
7519 if(x < 0)
7520 x = 0;
7521 else if((int32_t(x)&15) > 7)
7522 x=(int32_t(x)&0xF0)+16;
7523 else
7524 x=(int32_t(x)&0xF0);
7525
7526 break;
7527 }
7528
7529 sclk=0;
7530 clk3=0;
7531 break;
7532 }
7533 }
7534
7535 if((sclk&255)==0)
7536 {
7537 //hitdir = -1;
7538 sclk=0;
7539 }
7540 return 2;
7541 1138 }
7542
7543 bool enemy::can_slide()
7544 {
7545 if(sclk==0 || (hp<=0 && !immortal))
7546 return false;
7547
7548 if((sclk&255)==16 && (get_bit(quest_rules,qr_OLD_ENEMY_KNOCKBACK_COLLISION) || knockbackSpeed!=4 ? !canmove(sclk>>8,(zfix) (dmisc2==e2tSPLITHIT ? 1 : 12),0,true) : !canmove(sclk>>8,(zfix) (dmisc2==e2tSPLITHIT ? 1 : knockbackSpeed),0,true)))
7549 {
7550 return false;
7551 }
7552
7553 return true;
7554 }
7555
7556 bool enemy::fslide()
7557 {
7558 if(sclk==0 || (hp<=0 && !immortal))
7559 return false;
7560
7561 if((sclk&255)==16 && !canmove(sclk>>8,(zfix)12,spw_floater,true))
7562 {
7563 sclk=0;
7564 return false;
7565 }
7566
7567 --sclk;
7568
7569 switch(sclk>>8)
7570 {
7571 case up:
7572 if(y<=16)
7573 {
7574 sclk=0;
7575 return false;
7576 }
7577
7578 break;
7579
7580 case down:
7581 if(y>=160)
7582 {
7583 sclk=0;
7584 return false;
7585 }
7586
7587 break;
7588
7589 case left:
7590 if(x<=16)
7591 {
7592 sclk=0;
7593 return false;
7594 }
7595
7596 break;
7597
7598 case right:
7599 if(x>=240)
7600 {
7601 sclk=0;
7602 return false;
7603 }
7604
7605 break;
7606 }
7607 hitdir = (sclk>>8);
7608 switch(sclk>>8)
7609 {
7610 case up:
7611 y-=4;
7612 break;
7613
7614 case down:
7615 y+=4;
7616 break;
7617
7618 case left:
7619 x-=4;
7620 break;
7621
7622 case right:
7623 x+=4;
7624 break;
7625 }
7626
7627 if(!canmove(sclk>>8,(zfix)0,spw_floater,true))
7628 {
7629 switch(sclk>>8)
7630 {
7631 case up:
7632 case down:
7633 if((int32_t(y)&15) > 7)
7634 y=(int32_t(y)&0xF0)+16;
7635 else
7636 y=(int32_t(y)&0xF0);
7637
7638 break;
7639
7640 case left:
7641 case right:
7642 if((int32_t(x)&15) > 7)
7643 x=(int32_t(x)&0xF0)+16;
7644 else
7645 x=(int32_t(x)&0xF0);
7646
7647 break;
7648 }
7649
7650 sclk=0;
7651 clk3=0;
7652 }
7653
7654 if((sclk&255)==0)
7655 sclk=0;
7656
7657 return true;
7658 }
7659
7660 bool enemy::knockback(int32_t time, int32_t dir, int32_t speed)
7661 {
7662 if((hp<=0 && !immortal)) return false; //No knocking back dead/mid-knockback enemies
7663 if(!canmove(dir,(zfix)speed,0,0,0,15,15,true)) return false; //from slide(); collision check
7664 bool ret = sprite::knockback(time, dir, speed);
7665 if(ret) sclk = 0; //kill engine knockback if interrupted
7666 //! Perhaps also set hitdir here, if needed for timing? -Z
7667 return ret;
7668 }
7669
7670 3650 bool enemy::runKnockback()
7671 {
7672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3650 times.
3650 if((script_knockback_clk&0xFF)==0)
7673 {
7674 3650 script_knockback_clk = 0;
7675 3650 return false;
7676 }
7677 if(knockbackflags & FLAG_NOSCRIPTKNOCKBACK)
7678 {
7679 return false;
7680 }
7681 int32_t move = script_knockback_speed;
7682 int32_t kb_dir = script_knockback_clk>>8;
7683 --script_knockback_clk;
7684
7685 while(move>0)
7686 {
7687 int32_t thismove = zc_min(get_bit(quest_rules, qr_OLD_SCRIPTED_KNOCKBACK)?8:4, move);
7688 move -= thismove;
7689 hitdir = kb_dir;
7690 switch(kb_dir)
7691 {
7692 case r_up:
7693 case l_up:
7694 case up:
7695 y-=thismove;
7696 break;
7697
7698 case r_down:
7699 case l_down:
7700 case down:
7701 y+=thismove;
7702 break;
7703 }
7704 switch(kb_dir)
7705 {
7706 case l_up:
7707 case l_down:
7708 case left:
7709 x-=thismove;
7710 break;
7711
7712 case r_up:
7713 case r_down:
7714 case right:
7715 x+=thismove;
7716 break;
7717 }
7718 if (get_bit(quest_rules, qr_OLD_SCRIPTED_KNOCKBACK))
7719 {
7720 if(!canmove(kb_dir,(zfix)0,0,true))
7721 {
7722 script_knockback_clk=0;
7723 clk3=0;
7724 //Fix to grid
7725 switch(kb_dir)
7726 {
7727 case up:
7728 case down:
7729 break;
7730 default:
7731 if(x < 0)
7732 x = 0;
7733 else if((int32_t(x)&15) > 7)
7734 x=(int32_t(x)&0xF0)+16;
7735 else
7736 x=(int32_t(x)&0xF0);
7737 break;
7738 }
7739 switch(kb_dir)
7740 {
7741 case left:
7742 case right:
7743 break;
7744 default:
7745 if(y < 0)
7746 y = 0;
7747 else if((int32_t(y)&15) > 7)
7748 y=(int32_t(y)&0xF0)+16;
7749 else
7750 y=(int32_t(y)&0xF0);
7751 break;
7752 }
7753 break;
7754 }
7755 }
7756 else
7757 {
7758 if(!scr_canplace(x,y,0,true))
7759 {
7760 script_knockback_clk=0;
7761 clk3=0;
7762 //Fix to grid
7763 if (OFFGRID_ENEMY)
7764 {
7765 switch(kb_dir)
7766 {
7767 case up:
7768 case down:
7769 break;
7770 default:
7771 if(x < 0)
7772 x = 0;
7773 else if((int32_t(x)&7) > 3)
7774 x=(int32_t(x)&0xF8)+8;
7775 else
7776 x=(int32_t(x)&0xF8);
7777 break;
7778 }
7779 switch(kb_dir)
7780 {
7781 case left:
7782 case right:
7783 break;
7784 default:
7785 if(y < 0)
7786 y = 0;
7787 else if((int32_t(y)&7) > 3)
7788 y=(int32_t(y)&0xF8)+8;
7789 else
7790 y=(int32_t(y)&0xF8);
7791 break;
7792 }
7793 }
7794 else
7795 {
7796 switch(kb_dir)
7797 {
7798 case up:
7799 case down:
7800 break;
7801 default:
7802 if(x < 0)
7803 x = 0;
7804 else if((int32_t(x)&15) > 7)
7805 x=(int32_t(x)&0xF0)+16;
7806 else
7807 x=(int32_t(x)&0xF0);
7808 break;
7809 }
7810 switch(kb_dir)
7811 {
7812 case left:
7813 case right:
7814 break;
7815 default:
7816 if(y < 0)
7817 y = 0;
7818 else if((int32_t(y)&15) > 7)
7819 y=(int32_t(y)&0xF0)+16;
7820 else
7821 y=(int32_t(y)&0xF0);
7822 break;
7823 }
7824 }
7825 break;
7826 }
7827
7828 }
7829 }
7830 return true;
7831 3650 }
7832 // changes enemy's direction, checking restrictions
7833 // rate: 0 = no random changes, 16 = always random change
7834 // homing: 0 = none, 256 = always
7835 // grumble 0 = none, 4 = strongest appetite
7836 28 void enemy::newdir(int32_t newrate,int32_t newhoming,int32_t special)
7837 {
7838 28 int32_t ndir=-1;
7839
7840
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 6 times.
28 if(grumble != 0 && (zc_oldrand()&3)<abs(grumble)) //yes, I know checking if grumble is equal to if grumble == 0, but the latter makes the intention more clear to less experienced coders who might join.
7841 {
7842 6 int32_t i = Lwpns.idFirst(wBait);
7843
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(i >= 0) //idfirst returns -1 if it can't find any
7844 {
7845 weapon *w = (weapon*)Lwpns.spr(i);
7846 if (get_bit(quest_rules, qr_FIND_CLOSEST_BAIT))
7847 {
7848 int32_t currentrange;
7849 if (distance(x, y, w->x, w->y) < w->misc2 || w->misc2 == 0) currentrange = distance(x, y, w->x, w->y);
7850 else currentrange = -1;
7851 int curid = i;
7852 ++i; //increment beforehand cause we just checked the first bait weapon and all others must be after it. ...otherwise it wouldn't be the first. -Deedee
7853 for(; i<Lwpns.Count(); ++i)
7854 {
7855 weapon *lw = (weapon*)Lwpns.spr(i);
7856 if (lw->id == wBait && distance(x, y, lw->x, lw->y) < currentrange && (distance(x, y, lw->x, lw->y) < lw->misc2 || lw->misc2 == 0))
7857 {
7858 currentrange = distance(x, y, lw->x, lw->y);
7859 curid = i;
7860 }
7861 }
7862 i = curid;
7863 if (currentrange == -1) i = -1;
7864 }
7865 else
7866 {
7867 if (!(distance(x, y, w->x, w->y) < w->misc2 || w->misc2 == 0)) i = -1;
7868 }
7869 if (i >= 0)
7870 {
7871 int32_t bx = Lwpns.spr(i)->x;
7872 int32_t by = Lwpns.spr(i)->y;
7873
7874 if(abs(int32_t(y)-by)>14)
7875 {
7876 ndir = (by<y) ? up : down;
7877 if (grumble < 0 || (itemsbuf[((weapon*)Lwpns.spr(i))->parentitem].flags & ITEM_FLAG1)) ndir = oppositeDir[ndir];
7878 if(canmove(ndir,special,false))
7879 {
7880 dir=ndir;
7881 return;
7882 }
7883 }
7884
7885 ndir = (bx<x) ? left : right;
7886 if (grumble < 0 || (itemsbuf[((weapon*)Lwpns.spr(i))->parentitem].flags & ITEM_FLAG1)) ndir = oppositeDir[ndir];
7887 if(canmove(ndir,special,false))
7888 {
7889 dir=ndir;
7890 return;
7891 }
7892 }
7893 }
7894 6 }
7895
7896
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 5 times.
28 if((zc_oldrand()&255)<abs(newhoming))
7897 {
7898 5 ndir = lined_up(8,false);
7899
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (newhoming < 0 && ndir >= 0) ndir = oppositeDir[ndir];
7900
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
5 if(ndir>=0 && canmove(ndir,special,false))
7901 {
7902 2 dir=ndir;
7903 2 return;
7904 }
7905 3 }
7906
7907 26 int32_t i=0;
7908
7909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 for(; i<32; i++)
7910 {
7911 52 int32_t r=zc_oldrand();
7912
7913
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 35 times.
52 if((r&15)<newrate)
7914 17 ndir=(r>>4)&3;
7915 else
7916 35 ndir=dir;
7917
7918
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 26 times.
52 if(canmove(ndir,special,false))
7919 26 break;
7920 26 }
7921
7922
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if(i==32)
7923 {
7924 for(ndir=0; ndir<4; ndir++)
7925 {
7926 if(canmove(ndir,special,false))
7927 goto ok;
7928 }
7929
7930 ndir = (isSideViewGravity()) ? (zc_oldrand()&1 ? left : right) : -1; // Sideview enemies get trapped if their dir becomes -1
7931 //...Isn't that the point? I'm not sure I understand. Certainly beats phasing through walls... -Dimi
7932 }
7933
7934 ok:
7935 26 dir = ndir;
7936 28 }
7937
7938 void enemy::newdir()
7939 {
7940 newdir(4,0,spw_none);
7941 }
7942
7943 zfix enemy::distance_left()
7944 {
7945 int32_t a2=x.getInt();
7946 int32_t b2=y.getInt();
7947
7948 switch(dir)
7949 {
7950 case up:
7951 return (zfix)(b2&0xF);
7952
7953 case down:
7954 return (zfix)(16-(b2&0xF));
7955
7956 case left:
7957 return (zfix)(a2&0xF);
7958
7959 case right:
7960 return (zfix)(16-(a2&0xF));
7961 }
7962
7963 return (zfix)0;
7964 }
7965
7966 // keeps walking around
7967 void enemy::constant_walk(int32_t newrate,int32_t newhoming,int32_t special)
7968 {
7969 if(slide())
7970 return;
7971
7972 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock )
7973 return;
7974
7975 if(clk3<=0)
7976 {
7977 fix_coords(true);
7978 newdir(newrate,newhoming,special);
7979
7980 if(step==0)
7981 clk3=0;
7982 else
7983 clk3=int32_t(16.0/step);
7984 }
7985 else if(scored)
7986 {
7987 dir^=1;
7988 if (step != 0) clk3=int32_t(16.0/step)-clk3;
7989 else clk3=32767;
7990 }
7991
7992 if (step != 0) --clk3;
7993 move(step);
7994 }
7995
7996 void enemy::constant_walk()
7997 {
7998 constant_walk(4,0,spw_none);
7999 }
8000
8001 int32_t enemy::pos(int32_t newx,int32_t newy)
8002 {
8003 return (newy<<8)+newx;
8004 }
8005
8006 // for variable step rates
8007 void enemy::variable_walk(int32_t newrate,int32_t newhoming,int32_t special)
8008 {
8009 if(slide())
8010 return;
8011
8012 if(clk<0 || dying || stunclk || watch || step == 0 || ceiling || frozenclock )
8013 return;
8014
8015 zfix dx = (zfix)0;
8016 zfix dy = (zfix)0;
8017
8018 switch(dir)
8019 {
8020 case 8:
8021 case up:
8022 dy-=step;
8023 break;
8024
8025 case 12:
8026 case down:
8027 dy+=step;
8028 break;
8029
8030 case 14:
8031 case left:
8032 dx-=step;
8033 break;
8034
8035 case 10:
8036 case right:
8037 dx+=step;
8038 break;
8039
8040 case 15:
8041 case l_up:
8042 dx-=step;
8043 dy-=step;
8044 break;
8045
8046 case 9:
8047 case r_up:
8048 dx+=step;
8049 dy-=step;
8050 break;
8051
8052 case 13:
8053 case l_down:
8054 dx-=step;
8055 dy+=step;
8056 break;
8057
8058 case 11:
8059 case r_down:
8060 dx+=step;
8061 dy+=step;
8062 break;
8063 }
8064
8065 if(((int32_t(x)&15)==0 && (int32_t(y)&15)==0 && clk3!=pos(x,y)) ||
8066 m_walkflag(int32_t(x+dx),int32_t(y+dy), spw_halfstep, dir))
8067 {
8068 fix_coords();
8069 newdir(newrate,newhoming,special);
8070 clk3=pos(x,y);
8071 }
8072
8073 move(step);
8074 }
8075
8076 // pauses for a while after it makes a complete move (to a new square)
8077 1138 void enemy::halting_walk(int32_t newrate,int32_t newhoming,int32_t special,int32_t newhrate, int32_t haltcnt)
8078 {
8079
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1135 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
1138 if(sclk && clk2)
8080 {
8081 1 clk3=0;
8082 1 }
8083
8084
7/14
✓ Branch 0 taken 1138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1138 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1138 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1138 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1138 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1138 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1138 times.
1138 if(slide() || clk<0 || dying || stunclk || watch || ceiling || frozenclock)
8085 {
8086 return;
8087 }
8088
8089
2/2
✓ Branch 0 taken 417 times.
✓ Branch 1 taken 721 times.
1138 if(clk2>0)
8090 {
8091 417 --clk2;
8092 417 return;
8093 }
8094
8095
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 693 times.
721 if(clk3<=0)
8096 {
8097 28 fix_coords(true);
8098 28 newdir(newrate,newhoming,special);
8099 28 clk3=int32_t(16.0/step);
8100
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (step == 0) clk3 = 32767; //It used to return this in 2.53 and I'm unsure why; I'm guessing dividing by 0 gave max int? Either way, can't be 0 here or scripts break.
8101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if(clk2<0)
8102 {
8103 clk2=0;
8104 }
8105
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18 times.
28 else if((zc_oldrand()&15)<newhrate)
8106 {
8107 10 clk2=haltcnt;
8108 10 return;
8109 }
8110 18 }
8111
1/2
✓ Branch 0 taken 693 times.
✗ Branch 1 not taken.
693 else if(scored)
8112 {
8113 dir^=1;
8114
8115 if (step != 0) clk3=int32_t(16.0/step)-clk3;
8116 else clk3=32767;
8117 }
8118
8119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 711 times.
711 if (step != 0) --clk3;
8120 711 move(step);
8121 1138 }
8122
8123 // 8-directional movement, aligns to 8 pixels
8124 void enemy::constant_walk_8(int32_t newrate,int32_t newhoming,int32_t special)
8125 {
8126 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock)
8127 return;
8128
8129 if(clk3<=0)
8130 {
8131 newdir_8(newrate,newhoming,special);
8132 clk3=int32_t(8.0/step);
8133 if (step == 0) clk3 = 32767;
8134 }
8135
8136 if (step != 0) --clk3;
8137 move(step);
8138 }
8139 // 8-directional movement, aligns to 8 pixels
8140 void enemy::constant_walk_8_old(int32_t newrate,int32_t newhoming,int32_t special)
8141 {
8142 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock)
8143 return;
8144
8145 if(clk3<=0)
8146 {
8147 newdir_8(newrate,newhoming,special);
8148 clk3=int32_t(8.0/step);
8149 if (step == 0) clk3 = 32767;
8150 }
8151
8152 if (step != 0) --clk3;
8153 move(step);
8154 }
8155
8156 void enemy::halting_walk_8(int32_t newrate,int32_t newhoming, int32_t newclk,int32_t special,int32_t newhrate, int32_t haltcnt)
8157 {
8158 if(clk<0 || dying || stunclk || watch || frozenclock)
8159 return;
8160
8161 if(!canmove(dir,step,special,false))
8162 clk3=0;
8163
8164 if(clk2>0)
8165 {
8166 --clk2;
8167 return;
8168 }
8169
8170 if(clk3<=0)
8171 {
8172 newdir_8(newrate,newhoming,special);
8173 clk3=newclk;
8174
8175 if(clk2<0)
8176 {
8177 clk2=0;
8178 }
8179 else if((zc_oldrand()&15)<newhrate)
8180 {
8181 newdir_8(newrate,newhoming,special);
8182 clk2=haltcnt;
8183 return;
8184 }
8185 }
8186
8187 --clk3;
8188 move(step);
8189 }
8190
8191 // 8-directional movement, no alignment
8192 void enemy::variable_walk_8(int32_t newrate,int32_t newhoming, int32_t newclk,int32_t special)
8193 {
8194 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock)
8195 return;
8196
8197 if(!canmove(dir,step,special,false))
8198 clk3=0;
8199
8200 if(clk3<=0)
8201 {
8202 newdir_8(newrate,newhoming,special);
8203 clk3=newclk;
8204 }
8205
8206 --clk3;
8207 move(step);
8208 }
8209
8210 // same as above but with variable enemy size
8211 void enemy::variable_walk_8(int32_t newrate,int32_t newhoming, int32_t newclk,int32_t special,int32_t dx1,int32_t dy1,int32_t dx2,int32_t dy2)
8212 {
8213 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock)
8214 return;
8215
8216 if(!canmove(dir,step,special,dx1,dy1,dx2,dy2,false))
8217 clk3=0;
8218
8219 if(clk3<=0)
8220 {
8221 newdir_8(newrate,newhoming,special,dx1,dy1,dx2,dy2);
8222 clk3=newclk;
8223 }
8224
8225 --clk3;
8226 move(step);
8227 }
8228
8229 // the variable speed floater movement
8230 // ms is max speed
8231 // ss is step speed
8232 // s is step count
8233 // p is pause count
8234 // g is graduality :)
8235 //floater_walk(rate,hrate,dstep/100,(zfix)0,10,dmisc16,dmisc17);
8236 void enemy::floater_walk(int32_t newrate,int32_t newclk,zfix ms,zfix ss,int32_t s,int32_t p, int32_t g)
8237 {
8238 ++clk2;
8239 byte over_pit = overpit(this);
8240
8241 if(dmisc1 && over_pit) p = 0;
8242 switch(movestatus)
8243 {
8244 //! This needs a case 4 (landing)....if we want to halt, we move to case 4, and
8245 //! if the conditions prevent it, we jump back to case 2.
8246 case 0: // paused
8247 if(clk2>=p)
8248 {
8249 movestatus=1;
8250 clk2=0;
8251 }
8252
8253 break;
8254
8255 case 1: // speeding up
8256 if (s >= 0)
8257 {
8258 if(clk2<g*s)
8259 {
8260 if(!((clk2-1)%g))
8261 step+=ss;
8262 }
8263 else
8264 {
8265 movestatus=2;
8266 clk2=0;
8267 }
8268 }
8269 else
8270 {
8271 if(step < ms)
8272 {
8273 if(!((clk2-1)%g))
8274 {
8275 step+=ss;
8276 if (step >= ms) step = ms;
8277 }
8278 }
8279 else
8280 {
8281 step = ms;
8282 movestatus=2;
8283 clk2=0;
8284 }
8285 }
8286
8287 break;
8288
8289 case 2: // normal
8290 step=ms;
8291
8292 if(clk2>(dmisc15>0?dmisc15:48) && !(zc_oldrand()%(dmisc14>0?dmisc14:768)))
8293 {
8294 if (s >= 0) step=ss*s;
8295 else step=ms;
8296 movestatus=3;
8297 clk2=0;
8298 }
8299
8300 break;
8301
8302 case 3: // slowing down
8303 if (s >= 0)
8304 {
8305 if(clk2<=g*s)
8306 {
8307 { //don't slow down over pits
8308
8309 if(over_pit)
8310 {
8311 if(dmisc1)
8312 {
8313 step=ms;
8314 }
8315 }
8316 else //can slow down
8317 {
8318 if(!(clk2%g) && !dmisc1)
8319 step-=ss;
8320 }
8321 }
8322
8323
8324 }
8325 else
8326 {
8327 //if((moveflags&FLAG_CAN_PITFALL)) //don't check pits if the enemy ignores them
8328 //this doesn't help keese, as they have a z of 0.
8329 //they always nee to run this check.
8330 {
8331 if(over_pit &&!dmisc1)
8332 {
8333 --clk2; //if over a pit, don't land, and revert clock change
8334 }
8335 else //can land safely
8336 {
8337 movestatus=0;
8338 if(dmisc1&&!over_pit)
8339 step=0;
8340 clk2=0;
8341 }
8342 }
8343
8344 }
8345 }
8346 else
8347 {
8348 if(step > 0)
8349 {
8350 if(over_pit)
8351 {
8352 if(dmisc1)
8353 {
8354 step=ms;
8355 }
8356 }
8357 else //can slow down
8358 {
8359 if(!(clk2%g))
8360 step-=ss;
8361 }
8362 }
8363 else
8364 {
8365 //if((moveflags&FLAG_CAN_PITFALL)) //don't check pits if the enemy ignores them
8366 //this doesn't help keese, as they have a z of 0.
8367 //they always nee to run this check.
8368 if(over_pit)
8369 {
8370 step+=ss; //if over a pit, don't land, and revert clock change
8371 }
8372 else //can land safely
8373 {
8374 movestatus=0;
8375 step=0;
8376 clk2=0;
8377 }
8378 }
8379 }
8380
8381 break;
8382 }
8383
8384 variable_walk_8(movestatus==2?newrate:0,homing,newclk,spw_floater);
8385 }
8386
8387 void enemy::floater_walk(int32_t newrate,int32_t newclk,zfix s)
8388 {
8389 floater_walk(newrate,newclk,s,(zfix)0.125,3,80,32);
8390 }
8391
8392 // Checks if enemy is lined up with Hero. If so, returns direction Hero is
8393 // at as compared to enemy. Returns -1 if not lined up. Range is inclusive.
8394 5 int32_t enemy::lined_up(int32_t range, bool dir8)
8395 {
8396 5 int32_t lx = Hero.getX();
8397 5 int32_t ly = Hero.getY();
8398
8399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(abs(lx-int32_t(x))<=range)
8400 {
8401 if(ly<y)
8402 {
8403 return up;
8404 }
8405
8406 return down;
8407 }
8408
8409
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if(abs(ly-int32_t(y))<=range)
8410 {
8411
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(lx<x)
8412 {
8413 2 return left;
8414 }
8415
8416 return right;
8417 }
8418
8419
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(dir8)
8420 {
8421 if(abs(lx-x)-abs(ly-y)<=range)
8422 //if(abs(lx-x)-abs(ly-y)<=range && abs(ly-y)-abs(lx-x)<=range) //Fix floating enemies not seeking hero. -Tamamo
8423 {
8424 if(ly<y)
8425 {
8426 if(lx<x)
8427 {
8428 return l_up;
8429 }
8430 else
8431 {
8432 return r_up;
8433 }
8434 }
8435 else
8436 {
8437 if(lx<x)
8438 {
8439 return l_down;
8440 }
8441 else
8442 {
8443 return r_down;
8444 }
8445 }
8446 }
8447 }
8448
8449 3 return -1;
8450 5 }
8451
8452 // returns true if Hero is within 'range' pixels of the enemy
8453 bool enemy::HeroInRange(int32_t range)
8454 {
8455 int32_t lx = Hero.getX();
8456 int32_t ly = Hero.getY();
8457 return abs(lx-int32_t(x))<=range && abs(ly-int32_t(y))<=range;
8458 }
8459
8460 // place the enemy in line with Hero (red wizzrobes)
8461 void enemy::place_on_axis(bool floater, bool solid_ok)
8462 {
8463 int32_t lx=zc_min(zc_max(int32_t(Hero.getX())&0xF0,32),208);
8464 int32_t ly=zc_min(zc_max(int32_t(Hero.getY())&0xF0,32),128);
8465 int32_t pos2=zc_oldrand()%23;
8466 int32_t tried=0;
8467 bool last_resort,placed=false;
8468
8469
8470 do
8471 {
8472 if(pos2<14)
8473 {
8474 x=(pos2<<4)+16;
8475 y=ly;
8476 }
8477 else
8478 {
8479 x=lx;
8480 y=((pos2-14)<<4)+16;
8481 }
8482
8483 // Don't commit to a last resort if position is out of bounds.
8484 last_resort= !(x<32 || y<32 || x>=224 || y>=144);
8485
8486 if(abs(lx-int32_t(x))>16 || abs(ly-int32_t(y))>16)
8487 {
8488 // Red Wizzrobes should be able to appear on water, but not other
8489 // solid combos; however, they could appear on solid combos in 2.10,
8490 // and some quests depend on that.
8491 if((solid_ok || !m_walkflag(x,y,floater ? spw_water : spw_door, dir))
8492 && !flyerblocked(x,y,floater ? spw_floater : spw_door))
8493 placed=true;
8494 }
8495
8496 if(!placed && tried>=22 && last_resort)
8497 {
8498 placed=true;
8499 }
8500
8501 ++tried;
8502 pos2=(pos2+3)%23;
8503 }
8504 while(!placed);
8505
8506 if(y==ly)
8507 dir=(x<lx)?right:left;
8508 else
8509 dir=(y<ly)?down:up;
8510
8511 clk2=tried;
8512 }
8513
8514 int32_t enemy::n_frame_n_dir(int32_t frames, int32_t ndir, int32_t f4)
8515 {
8516 int32_t t = o_tile;
8517 int32_t b = o_tile;
8518
8519 // Darknuts, but also Wizzrobes and Wallmasters
8520 switch(family)
8521 {
8522 case eeWALK:
8523 if(dmisc9==e9tPOLSVOICE && clk2>=0 && do_animation)
8524 {
8525 tile=s_tile;
8526 t=s_tile;
8527 b=s_tile;
8528 }
8529
8530 break;
8531
8532 case eeTRAP:
8533 if(dummy_int[1] && guysbuf[id].flags2 & eneflag_trp2 && do_animation) // Just to make sure
8534 {
8535 tile=s_tile;
8536 t=s_tile;
8537 b=s_tile;
8538 }
8539
8540 break;
8541
8542 case eeSPINTILE:
8543 if(misc>=96 && do_animation)
8544 {
8545 tile=o_tile+frames*ndir;
8546 t=tile;
8547 }
8548
8549 break;
8550 }
8551 if ( do_animation )
8552 {
8553 if(ndir!=0) switch(frames)
8554 {
8555 case 2:
8556 tiledir_small(dir,ndir==4);
8557 break;
8558
8559 case 3:
8560 tiledir_three(dir);
8561 break;
8562
8563 case 4:
8564 tiledir(dir,ndir==4);
8565 break;
8566 }
8567
8568 if(family==eeWALK)
8569 tile=zc_min(tile+f4, t+frames*(zc_max(dir, 0)+1)-1);
8570 else
8571 tile+=f4;
8572 }
8573 return b;
8574 }
8575
8576 void enemy::tiledir_three(int32_t ndir)
8577 {
8578 if ( !do_animation ) return;
8579 flip=0;
8580
8581 switch(ndir)
8582 {
8583 case right:
8584 tile+=3;
8585 [[fallthrough]];
8586
8587 case left:
8588 tile+=3;
8589 [[fallthrough]];
8590
8591 case down:
8592 tile+=3;
8593 [[fallthrough]];
8594
8595 case up:
8596 break;
8597 }
8598 }
8599
8600 void enemy::tiledir_small(int32_t ndir, bool fourdir)
8601 {
8602 if ( !do_animation ) return;
8603 flip=0;
8604
8605 switch(ndir)
8606 {
8607 case 8:
8608 case up:
8609 break;
8610
8611 case 12:
8612 case down:
8613 tile+=2;
8614 break;
8615
8616 case 14:
8617 case left:
8618 tile+=4;
8619 break;
8620
8621 case 10:
8622 case right:
8623 tile+=6;
8624 break;
8625
8626 case 9:
8627 case r_up:
8628 if(fourdir)
8629 break;
8630
8631 tile+=10;
8632 break;
8633
8634 case 11:
8635 case r_down:
8636 if(fourdir)
8637 tile+=2;
8638 else
8639 tile+=14;
8640
8641 break;
8642
8643 case 13:
8644 case l_down:
8645 if(fourdir)
8646 tile+=2;
8647 else
8648 tile+=12;
8649
8650 break;
8651
8652 case 15:
8653 case l_up:
8654 if(fourdir)
8655 break;
8656
8657 tile+=8;
8658 break;
8659
8660 default:
8661 //dir=(zc_oldrand()*100)%8;
8662 //tiledir_small(dir);
8663 // flip=zc_oldrand()&3;
8664 // tile=(zc_oldrand()*100000)%NEWMAXTILES;
8665 break;
8666 }
8667 }
8668
8669 void enemy::tiledir(int32_t ndir, bool fourdir)
8670 {
8671 if ( !do_animation ) return;
8672 flip=0;
8673
8674 switch(ndir)
8675 {
8676 case 8:
8677 case up:
8678 break;
8679
8680 case 12:
8681 case down:
8682 tile+=4;
8683 break;
8684
8685 case 14:
8686 case left:
8687 tile+=8;
8688 break;
8689
8690 case 10:
8691 case right:
8692 tile+=12;
8693 break;
8694
8695 case 9:
8696 case r_up:
8697 if(fourdir)
8698 break;
8699 else
8700 tile+=24;
8701
8702 break;
8703
8704 case 11:
8705 case r_down:
8706 if(fourdir)
8707 tile+=4;
8708 else
8709 tile+=32;
8710
8711 break;
8712
8713 case 13:
8714 case l_down:
8715 if(fourdir)
8716 tile+=4;
8717 else
8718 tile+=28;
8719
8720 break;
8721
8722 case 15:
8723 case l_up:
8724 if(fourdir)
8725 break;
8726 else
8727 tile+=20;
8728
8729 break;
8730
8731 default:
8732 //dir=(zc_oldrand()*100)%8;
8733 //tiledir(dir);
8734 // flip=zc_oldrand()&3;
8735 // tile=(zc_oldrand()*100000)%NEWMAXTILES;
8736 break;
8737 }
8738 }
8739
8740 void enemy::tiledir_big(int32_t ndir, bool fourdir)
8741 {
8742 if ( !do_animation ) return;
8743 flip=0;
8744
8745 switch(ndir)
8746 {
8747 case 8:
8748 case up:
8749 break;
8750
8751 case 12:
8752 case down:
8753 tile+=8;
8754 break;
8755
8756 case 14:
8757 case left:
8758 tile+=40;
8759 break;
8760
8761 case 10:
8762 case right:
8763 tile+=48;
8764 break;
8765
8766 case 9:
8767 case r_up:
8768 if(fourdir)
8769 break;
8770
8771 tile+=88;
8772 break;
8773
8774 case 11:
8775 case r_down:
8776 if(fourdir)
8777 tile+=8;
8778 else
8779 tile+=128;
8780
8781 break;
8782
8783 case 13:
8784 case l_down:
8785 if(fourdir)
8786 tile+=8;
8787 else
8788 tile+=120;
8789
8790 break;
8791
8792 case 15:
8793 case l_up:
8794 if(fourdir)
8795 break;
8796
8797 tile+=80;
8798 break;
8799
8800 default:
8801 //dir=(zc_oldrand()*100)%8;
8802 //tiledir_big(dir);
8803 // flip=zc_oldrand()&3;
8804 // tile=(zc_oldrand()*100000)%NEWMAXTILES;
8805 break;
8806 }
8807 }
8808
8809 3782 void enemy::update_enemy_frame()
8810 {
8811
2/4
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3782 times.
3782 if(fallclk||drownclk) return;
8812
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 if (!do_animation)
8813 return;
8814
8815
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3782 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3782 if (get_bit(quest_rules,qr_OLD_TILE_INITIALIZATION) || tile == 0) tile = o_tile; //tile was initialized here before. It needs to be initialized here as well.
8816
8817
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
3782 if(get_bit(quest_rules,qr_ANONE_NOANIM)
8818
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3782 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3782 && anim == aNONE && family != eeGUY)
8819 return;
8820
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 int32_t newfrate = zc_max(frate,4);
8821 3782 int32_t f4=abs(clk/(newfrate/4)); // casts clk to [0,1,2,3]
8822 3782 int32_t f2=abs(clk/(newfrate/2)); // casts clk to [0,1]
8823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3782 times.
3782 int32_t fx = get_bit(quest_rules, qr_NEWENEMYTILES) ? f4 : f2;
8824 3782 tile = o_tile;
8825 3782 int32_t basetile = o_tile;
8826 3782 int32_t tilerows = 1; // How many rows of tiles? The Extend code needs to know.
8827 3782 bool ignore_extend = false;
8828
4/40
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 355 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 1026 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 1364 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1037 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
3782 switch(anim)
8829 {
8830
8831 case aDONGO:
8832 {
8833 int32_t fr = stunclk>0 ? 16 : 8;
8834
8835 if(!dying && clk2>0 && clk2<=64)
8836 {
8837 // bloated
8838 switch(dir)
8839 {
8840 case up:
8841 tile+=9;
8842 flip=0;
8843 xofs=0;
8844 dummy_int[1]=0; //no additional tiles
8845 break;
8846
8847 case down:
8848 tile+=7;
8849 flip=0;
8850 xofs=0;
8851 dummy_int[1]=0; //no additional tiles
8852 break;
8853
8854 case left:
8855 flip=1;
8856 tile+=4;
8857 xofs=16;
8858 dummy_int[1]=1; //second tile is next tile
8859 break;
8860
8861 case right:
8862 flip=0;
8863 tile+=5;
8864 xofs=16;
8865 dummy_int[1]=-1; //second tile is previous tile
8866 break;
8867 }
8868 }
8869 else if(!dying || clk2>19)
8870 {
8871 // normal
8872 switch(dir)
8873 {
8874 case up:
8875 tile+=8;
8876 flip=(clk&fr)?1:0;
8877 xofs=0;
8878 dummy_int[1]=0; //no additional tiles
8879 break;
8880
8881 case down:
8882 tile+=6;
8883 flip=(clk&fr)?1:0;
8884 xofs=0;
8885 dummy_int[1]=0; //no additional tiles
8886 break;
8887
8888 case left:
8889 flip=1;
8890 tile+=(clk&fr)?2:0;
8891 xofs=16;
8892 dummy_int[1]=1; //second tile is next tile
8893 break;
8894
8895 case right:
8896 flip=0;
8897 tile+=(clk&fr)?3:1;
8898 xofs=16;
8899 dummy_int[1]=-1; //second tile is next tile
8900 break;
8901 }
8902 }
8903 }
8904 break;
8905
8906 case aNEWDONGO:
8907 {
8908 int32_t fr4=0;
8909
8910 if(!dying && clk2>0 && clk2<=64)
8911 {
8912 // bloated
8913 if(clk2>=0)
8914 {
8915 fr4=3;
8916 }
8917
8918 if(clk2>=16)
8919 {
8920 fr4=2;
8921 }
8922
8923 if(clk2>=32)
8924 {
8925 fr4=1;
8926 }
8927
8928 if(clk2>=48)
8929 {
8930 fr4=0;
8931 }
8932
8933 switch(dir)
8934 {
8935 case up:
8936 xofs=0;
8937 tile+=8+fr4;
8938 dummy_int[1]=0; //no additional tiles
8939 break;
8940
8941 case down:
8942 xofs=0;
8943 tile+=12+fr4;
8944 dummy_int[1]=0; //no additional tiles
8945 break;
8946
8947 case left:
8948 tile+=29+(2*fr4);
8949 xofs=16;
8950 dummy_int[1]=-1; //second tile is previous tile
8951 break;
8952
8953 case right:
8954 tile+=49+(2*fr4);
8955 xofs=16;
8956 dummy_int[1]=-1; //second tile is previous tile
8957 break;
8958 }
8959 }
8960 else if(!dying || clk2>19)
8961 {
8962 // normal
8963 switch(dir)
8964 {
8965 case up:
8966 xofs=0;
8967 tile+=((clk&12)>>2);
8968 dummy_int[1]=0; //no additional tiles
8969 break;
8970
8971 case down:
8972 xofs=0;
8973 tile+=4+((clk&12)>>2);
8974 dummy_int[1]=0; //no additional tiles
8975 break;
8976
8977 case left:
8978 tile+=21+((clk&12)>>1);
8979 xofs=16;
8980 dummy_int[1]=-1; //second tile is previous tile
8981 break;
8982
8983 case right:
8984 flip=0;
8985 tile+=41+((clk&12)>>1);
8986 xofs=16;
8987 dummy_int[1]=-1; //second tile is previous tile
8988 break;
8989 }
8990 }
8991 }
8992 break;
8993
8994 case aDONGOBS:
8995 {
8996 int32_t fr4=0;
8997
8998 if(!dying && clk2>0 && clk2<=64)
8999 {
9000 // bloated
9001 if(clk2>=0)
9002 {
9003 fr4=3;
9004 }
9005
9006 if(clk2>=16)
9007 {
9008 fr4=2;
9009 }
9010
9011 if(clk2>=32)
9012 {
9013 fr4=1;
9014 }
9015
9016 if(clk2>=48)
9017 {
9018 fr4=0;
9019 }
9020
9021 switch(dir)
9022 {
9023 case up:
9024 tile+=28+fr4;
9025 yofs+=8;
9026 dummy_int[1]=-20; //second tile change
9027 dummy_int[2]=0; //new xofs change
9028 dummy_int[3]=-16; //new xofs change
9029 break;
9030
9031 case down:
9032 tile+=12+fr4;
9033 yofs-=8;
9034 dummy_int[1]=20; //second tile change
9035 dummy_int[2]=0; //new xofs change
9036 dummy_int[3]=16; //new xofs change
9037 break;
9038
9039 case left:
9040 tile+=49+(2*fr4);
9041 xofs+=8;
9042 dummy_int[1]=-1; //second tile change
9043 dummy_int[2]=-16; //new xofs change
9044 dummy_int[3]=0; //new xofs change
9045 break;
9046
9047 case right:
9048 tile+=69+(2*fr4);
9049 xofs+=8;
9050 dummy_int[1]=-1; //second tile change
9051 dummy_int[2]=-16; //new xofs change
9052 dummy_int[3]=0; //new xofs change
9053 break;
9054 }
9055 }
9056 else if(!dying || clk2>19)
9057 {
9058 // normal
9059 switch(dir)
9060 {
9061 case up:
9062 tile+=20+((clk&24)>>3);
9063 yofs+=8;
9064 dummy_int[1]=-20; //second tile change
9065 dummy_int[2]=0; //new xofs change
9066 dummy_int[3]=-16; //new xofs change
9067 break;
9068
9069 case down:
9070 tile+=4+((clk&24)>>3);
9071 yofs-=8;
9072 dummy_int[1]=20; //second tile change
9073 dummy_int[2]=0; //new xofs change
9074 dummy_int[3]=16; //new xofs change
9075 break;
9076
9077 case left:
9078 xofs=-8;
9079 tile+=40+((clk&24)>>2);
9080 dummy_int[1]=1; //second tile change
9081 dummy_int[2]=16; //new xofs change
9082 dummy_int[3]=0; //new xofs change
9083 break;
9084
9085 case right:
9086 tile+=60+((clk&24)>>2);
9087 xofs=-8;
9088 dummy_int[1]=1; //second tile change
9089 dummy_int[2]=16; //new xofs change
9090 dummy_int[3]=0; //new xofs change
9091 break;
9092 }
9093 }
9094 }
9095 break;
9096
9097 case aWIZZ:
9098 {
9099 // if(d->misc1)
9100 if(dmisc1)
9101 {
9102 if(clk&8)
9103 {
9104 ++tile;
9105 }
9106 }
9107 else
9108 {
9109 if(frame&4)
9110 {
9111 ++tile;
9112 }
9113 }
9114
9115 switch(dir)
9116 {
9117 case 9:
9118 case 15:
9119 case up:
9120 tile+=2;
9121 break;
9122
9123 case down:
9124 break;
9125
9126 case 13:
9127 case left:
9128 flip=1;
9129 break;
9130
9131 default:
9132 flip=0;
9133 break;
9134 }
9135 }
9136 break;
9137
9138 case aNEWWIZZ:
9139 {
9140 tiledir(dir,true);
9141
9142 // if(d->misc1) //walking wizzrobe
9143 if(dmisc1) //walking wizzrobe
9144 {
9145 if(clk&8)
9146 {
9147 tile+=2;
9148 }
9149
9150 if(clk&4)
9151 {
9152 tile+=1;
9153 }
9154
9155 if(!(dummy_bool[1]||dummy_bool[2])) //should never be charging or firing for these wizzrobes
9156 {
9157 if(dummy_int[1]>0)
9158 {
9159 tile+=40;
9160 }
9161 }
9162 }
9163 else
9164 {
9165 if(dummy_bool[1]||dummy_bool[2])
9166 {
9167 tile+=20;
9168
9169 if(dummy_bool[2])
9170 {
9171 tile+=20;
9172 }
9173 }
9174
9175 tile+=((frame>>1)&3);
9176 }
9177 }
9178 break;
9179
9180 case a3FRM:
9181 {
9182 basetile = n_frame_n_dir(3, 0, (f4==3) ? 1 : f4);
9183 }
9184 break;
9185
9186 case a3FRM4DIR:
9187 {
9188 basetile = n_frame_n_dir(3, 4, (f4==3) ? 1 : f4);
9189 }
9190 break;
9191
9192 case aVIRE:
9193 {
9194 if(dir==up)
9195 {
9196 tile+=2;
9197 }
9198
9199 tile+=fx;
9200 }
9201 break;
9202
9203 case aROPE:
9204 {
9205 tile+=(1-fx);
9206 flip = dir==left ? 1:0;
9207 }
9208 break;
9209
9210 case aZORA:
9211 {
9212 int32_t dl;
9213
9214 if(clk<36)
9215 {
9216 dl=clk+5;
9217 goto waves2;
9218 }
9219
9220 if(clk<36+66)
9221 tile=(dir==up)?o_tile+1:o_tile;
9222 else
9223 {
9224 dl=clk-36-66;
9225 waves2:
9226 tile=((dl/11)&1)+s_tile;
9227 basetile = s_tile;
9228 }
9229 }
9230 break;
9231
9232 case aNEWZORA:
9233 {
9234 f4=(clk/16)%4;
9235
9236 tiledir(dir,true);
9237 int32_t dl;
9238
9239 if((clk>35)&&(clk<36+67)) //surfaced
9240 {
9241 if((clk>=(35+10))&&(clk<(38+56))) //mouth open
9242 {
9243 tile+=80;
9244 } //mouth closed
9245 else
9246 {
9247 tile+=40;
9248 }
9249
9250 tile+=f4;
9251 }
9252 else
9253 {
9254 if(clk<36)
9255 {
9256 dl=clk+5;
9257 }
9258 else
9259 {
9260 dl=clk-36-66;
9261 }
9262
9263 tile+=((dl/5)&3);
9264 }
9265 }
9266 break;
9267
9268 case a4FRM4EYE:
9269 case a2FRM4EYE:
9270 case a4FRM8EYE:
9271 case a4FRM8EYEB: //big version
9272 case a4FRM4EYEB:
9273 {
9274 tilerows = 2;
9275 int fakex = x + 8*(zc_max(1,txsz)-1);
9276 int fakey = y + 8*(zc_max(1,tysz)-1);
9277 double _MSVC2022_tmp1, _MSVC2022_tmp2;
9278 double ddir=atan2_MSVC2022_FIX(double(fakey-(Hero.y)),double(Hero.x-fakex));
9279 int32_t lookat=zc_oldrand()&15;
9280
9281 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
9282 {
9283 lookat=l_down;
9284 }
9285 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
9286 {
9287 lookat=down;
9288 }
9289 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
9290 {
9291 lookat=r_down;
9292 }
9293 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
9294 {
9295 lookat=right;
9296 }
9297 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
9298 {
9299 lookat=r_up;
9300 }
9301 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
9302 {
9303 lookat=up;
9304 }
9305 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
9306 {
9307 lookat=l_up;
9308 }
9309 else
9310 {
9311 lookat=left;
9312 }
9313
9314 int32_t dir2 = dir;
9315 dir = lookat;
9316 if (anim != a4FRM8EYEB && anim != a4FRM4EYEB) basetile = n_frame_n_dir(anim==a2FRM4EYE ? 2:4, anim==a4FRM8EYE ? 8 : 4, anim==a2FRM4EYE ? (f2&1):f4);
9317 else
9318 {
9319 tiledir_big(dir,(anim == a4FRM4EYEB));
9320 tile+=2*f4;
9321 ignore_extend = true;
9322 }
9323 dir = dir2;
9324 }
9325 break;
9326
9327 case aFLIP:
9328 {
9329 1026 flip = f2&1;
9330 }
9331 1026 break;
9332
9333 case a2FRM:
9334 {
9335 tile += (1-f2);
9336 }
9337 break;
9338
9339 case a2FRMB:
9340 {
9341 tile+= 2*(1-f2);
9342 ignore_extend = true;
9343 }
9344 break;
9345
9346 case a2FRM4DIR:
9347 {
9348 basetile = n_frame_n_dir(2, 4, f2&1);
9349 }
9350 break;
9351
9352 case a4FRM4DIRF:
9353 {
9354 basetile = n_frame_n_dir(4,4,f4);
9355
9356 if(clk2>0) //stopped to fire
9357 {
9358 tile+=20;
9359
9360 if(clk2<17) //firing
9361 {
9362 tile+=20;
9363 }
9364 }
9365 }
9366 break;
9367
9368 case a4FRM4DIR:
9369 {
9370 basetile = n_frame_n_dir(4,4,f4);
9371 }
9372 break;
9373
9374 case a4FRM8DIRF:
9375 {
9376 tilerows = 2;
9377 basetile = n_frame_n_dir(4,8,f4);
9378
9379 if(clk2>0) //stopped to fire
9380 {
9381 tile+=40;
9382
9383 if(clk2<17) //firing
9384 {
9385 tile+=40;
9386 }
9387 }
9388 }
9389 break;
9390
9391 case a4FRM8DIRB:
9392 case a4FRM8DIRFB:
9393 {
9394 tilerows = 2;
9395 tiledir_big(dir,false);
9396 tile+=2*f4;
9397 if(clk2>0 && anim == a4FRM8DIRFB) //stopped to fire
9398 {
9399 tile+=80;
9400
9401 if(clk2<17) //firing
9402 {
9403 tile+=80;
9404 }
9405 }
9406 ignore_extend = true;
9407 }
9408 break;
9409
9410 case a4FRM4DIRB:
9411 case a4FRM4DIRFB:
9412 {
9413 tilerows = 2;
9414 tiledir_big(dir,true);
9415 tile+=2*f4;
9416 if(clk2>0 && anim == a4FRM4DIRFB) //stopped to fire
9417 {
9418 tile+=40;
9419
9420 if(clk2<17) //firing
9421 {
9422 tile+=40;
9423 }
9424 }
9425 ignore_extend = true;
9426 }
9427 break;
9428
9429 case aOCTO:
9430 {
9431
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 890 times.
✓ Branch 4 taken 140 times.
1364 switch(dir)
9432 {
9433 case up:
9434 239 flip = 2;
9435 239 break;
9436
9437 case down:
9438 95 flip = 0;
9439 95 break;
9440
9441 case left:
9442 890 flip = 0;
9443 890 tile += 2;
9444 890 break;
9445
9446 case right:
9447 140 flip = 1;
9448 140 tile += 2;
9449 140 break;
9450 }
9451
9452 1364 tile+=f2;
9453 }
9454 1364 break;
9455
9456 case aWALK:
9457 {
9458 switch(dir)
9459 {
9460 case up:
9461 tile+=3;
9462 flip = f2;
9463 break;
9464
9465 case down:
9466 tile+=2;
9467 flip = f2;
9468 break;
9469
9470 case left:
9471 flip=1;
9472 tile += f2;
9473 break;
9474
9475 case right:
9476 flip=0;
9477 tile += f2;
9478 break;
9479 }
9480 }
9481 break;
9482
9483 case aDWALK:
9484 {
9485 if((get_bit(quest_rules,qr_BRKNSHLDTILES)) && (dummy_bool[1]==true))
9486 {
9487 tile=s_tile;
9488 basetile = s_tile;
9489 }
9490
9491 switch(dir)
9492 {
9493 case up:
9494 tile+=2;
9495 flip=f2;
9496 break;
9497
9498 case down:
9499 flip=0;
9500 tile+=(1-f2);
9501 break;
9502
9503 case left:
9504 flip=1;
9505 tile+=(3+f2);
9506 break;
9507
9508 case right:
9509 flip=0;
9510 tile+=(3+f2);
9511 break;
9512 }
9513 }
9514 break;
9515
9516 case aTEK:
9517 {
9518
2/2
✓ Branch 0 taken 900 times.
✓ Branch 1 taken 137 times.
1037 if(misc==0)
9519 {
9520 137 tile += f2;
9521 137 }
9522
2/2
✓ Branch 0 taken 452 times.
✓ Branch 1 taken 448 times.
900 else if(misc!=1)
9523 {
9524 448 ++tile;
9525 448 }
9526 }
9527 1037 break;
9528
9529 case aNEWTEK:
9530 {
9531 if(step<0) //up
9532 {
9533 switch(clk3)
9534 {
9535 case left:
9536 flip=0;
9537 tile+=20;
9538 break;
9539
9540 case right:
9541 flip=0;
9542 tile+=24;
9543 break;
9544 }
9545 }
9546 else if(step==0)
9547 {
9548 switch(clk3)
9549 {
9550 case left:
9551 flip=0;
9552 tile+=8;
9553 break;
9554
9555 case right:
9556 flip=0;
9557 tile+=12;
9558 break;
9559 }
9560 } //down
9561 else
9562 {
9563 switch(clk3)
9564 {
9565 case left:
9566 flip=0;
9567 tile+=28;
9568 break;
9569
9570 case right:
9571 flip=0;
9572 tile+=32;
9573 break;
9574 }
9575 }
9576
9577 if(misc==0)
9578 {
9579 tile+=f4;
9580 }
9581 else if(misc!=1)
9582 {
9583 tile+=2;
9584 }
9585 }
9586 break;
9587
9588 case aARMOS:
9589 {
9590 if(!fading)
9591 {
9592 tile += fx;
9593
9594 if(dir==up)
9595 tile += 2;
9596 }
9597 }
9598 break;
9599
9600 case aARMOS4:
9601 {
9602 switch(dir)
9603 {
9604 case up:
9605 flip=0;
9606 break;
9607
9608 case down:
9609 flip=0;
9610 tile+=4;
9611 break;
9612
9613 case left:
9614 flip=0;
9615 tile+=8;
9616 break;
9617
9618 case right:
9619 flip=0;
9620 tile+=12;
9621 break;
9622 }
9623
9624 if(!fading)
9625 {
9626 tile+=f4;
9627 }
9628 }
9629 break;
9630
9631 case aGHINI:
9632 {
9633 switch(dir)
9634 {
9635 case 8:
9636 case 9:
9637 case up:
9638 ++tile;
9639 flip=0;
9640 break;
9641
9642 case 15:
9643 ++tile;
9644 flip=1;
9645 break;
9646
9647 case 10:
9648 case 11:
9649 case right:
9650 flip=1;
9651 break;
9652
9653 default:
9654 flip=0;
9655 break;
9656 }
9657 }
9658 break;
9659
9660 case a2FRMPOS:
9661 {
9662 tile+=posframe;
9663 }
9664 break;
9665
9666 case a4FRMPOS4DIR:
9667 {
9668 basetile = n_frame_n_dir(4,4,0);
9669 // tile+=f2;
9670 tile+=posframe;
9671 }
9672 break;
9673
9674 case a4FRMPOS4DIRF:
9675 {
9676 basetile = n_frame_n_dir(4,4,0);
9677
9678 if(clk2>0) //stopped to fire
9679 {
9680 tile+=20;
9681
9682 if(clk2<17) //firing
9683 {
9684 tile+=20;
9685 }
9686 }
9687
9688 // tile+=f2;
9689 tile+=posframe;
9690 }
9691 break;
9692
9693 case a4FRMPOS8DIR:
9694 {
9695 tilerows = 2;
9696 int32_t n = tile;
9697 basetile = n_frame_n_dir(4,8,0);
9698 // tile+=f2;
9699 tile+=posframe;
9700 }
9701 break;
9702
9703 case a4FRMPOS8DIRF:
9704 {
9705 tilerows = 2;
9706 basetile = n_frame_n_dir(4,8,0);
9707
9708 if(clk2>0) //stopped to fire
9709 {
9710 tile+=40;
9711
9712 if(clk2<17) //firing
9713 {
9714 tile+=40;
9715 }
9716 }
9717
9718 tile+=posframe;
9719 }
9720 break;
9721
9722 case aNEWLEV:
9723 {
9724 tiledir(dir,true);
9725
9726 switch(misc)
9727 {
9728 case -1:
9729 case 0:
9730 return;
9731
9732 case 1:
9733
9734 // case 5: cs = d->misc2; break;
9735 case 5:
9736 cs = dmisc2;
9737 break;
9738
9739 case 2:
9740 case 4:
9741 tile += 20;
9742 break;
9743
9744 case 3:
9745 tile += 40;
9746 break;
9747 }
9748
9749 tile+=f4;
9750 }
9751 break;
9752
9753 case aLEV:
9754 {
9755 f4 = ((clk/5)&1);
9756
9757 switch(misc)
9758 {
9759 case -1:
9760 case 0:
9761 return;
9762
9763 case 1:
9764
9765 // case 5: tile += (f2) ? 1 : 0; cs = d->misc2; break;
9766 case 5:
9767 tile += (f2) ? 1 : 0;
9768 cs = dmisc2;
9769 break;
9770
9771 case 2:
9772 case 4:
9773 tile += 2;
9774 break;
9775
9776 case 3:
9777 tile += (f4) ? 4 : 3;
9778 break;
9779 }
9780 }
9781 break;
9782
9783 case aWALLM:
9784 {
9785 if(!dummy_bool[1])
9786 {
9787 tile += f2;
9788 }
9789 }
9790 break;
9791
9792 case aNEWWALLM:
9793 {
9794 int32_t tempdir=0;
9795
9796 switch(misc)
9797 {
9798 case 1:
9799 case 2:
9800 tempdir=clk3;
9801 break;
9802
9803 case 3:
9804 case 4:
9805 case 5:
9806 tempdir=dir;
9807 break;
9808
9809 case 6:
9810 case 7:
9811 tempdir=clk3^1;
9812 break;
9813 }
9814
9815 tiledir(tempdir,true);
9816
9817 if(!dummy_bool[1])
9818 {
9819 tile+=f4;
9820 }
9821 }
9822 break;
9823
9824 case a4FRMNODIR:
9825 {
9826 tile+=f4;
9827 }
9828 break;
9829
9830 } // switch(d->anim)
9831
9832 // flashing
9833 // if(d->flags2 & guy_flashing)
9834
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 if(flags2 & guy_flashing)
9835 {
9836 cs = (frame&3) + 6;
9837 }
9838
9839
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 if(flags2&guy_transparent)
9840 {
9841 drawstyle=1;
9842 }
9843
9844 3782 int32_t change = tile-basetile;
9845
9846
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3782 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3782 if(extend > 2 && (!ignore_extend || get_bit(quest_rules, qr_BROKEN_BIG_ENEMY_ANIMATION)))
9847 {
9848 if(basetile/TILES_PER_ROW==(basetile+((txsz*change)/tilerows))/TILES_PER_ROW)
9849 {
9850 tile=basetile+txsz*change;
9851 }
9852 else
9853 {
9854 tile=basetile+(txsz*change)+((tysz-1)*TILES_PER_ROW)*(((basetile+txsz*change)/TILES_PER_ROW)-(basetile/TILES_PER_ROW));
9855 }
9856 }
9857 else
9858 {
9859 3782 tile=basetile+change;
9860 }
9861 3782 }
9862
9863 8 int32_t wpnsfx(int32_t wpn)
9864 {
9865
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 switch(wpn)
9866 {
9867 case ewFireTrail:
9868 case ewFlame:
9869 case ewFlame2Trail:
9870 case ewFlame2:
9871 return WAV_FIRE;
9872
9873 case ewWind:
9874 case ewMagic:
9875 return WAV_WAND;
9876
9877 case ewIce:
9878 return WAV_ZN1ICE;
9879
9880 case ewRock:
9881
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if(get_bit(quest_rules,qr_MORESOUNDS)) return WAV_ZN1ROCK;
9882 8 break;
9883
9884 case ewFireball2:
9885 case ewFireball:
9886 if(get_bit(quest_rules,qr_MORESOUNDS)) return WAV_ZN1FIREBALL;
9887 }
9888
9889 8 return -1;
9890 8 }
9891
9892 7432 int32_t enemy::run_script(int32_t mode)
9893 {
9894
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7432 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7432 if(switch_hooked && !get_bit(quest_rules, qr_SWITCHOBJ_RUN_SCRIPT)) return RUNSCRIPT_OK;
9895
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7432 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7432 if (script <= 0 || !doscript || FFCore.getQuestHeaderInfo(vZelda) < 0x255 || FFCore.system_suspend[susptNPCSCRIPTS])
9896 7432 return RUNSCRIPT_OK;
9897 int32_t ret = RUNSCRIPT_OK;
9898 alloc_scriptmem();
9899 switch(mode)
9900 {
9901 case MODE_NORMAL:
9902 return ZScriptVersion::RunScript(SCRIPT_NPC, script, getUID());
9903 case MODE_WAITDRAW:
9904 if(waitdraw)
9905 {
9906 ret = ZScriptVersion::RunScript(SCRIPT_NPC, script, getUID());
9907 waitdraw = 0;
9908 }
9909 break;
9910 }
9911 return ret;
9912 7432 }
9913
9914 /********************************/
9915 /********* Guy Class **********/
9916 /********************************/
9917
9918 // good guys, fires, fairy, and other non-enemies
9919 // based on enemy class b/c guys in dungeons act sort of like enemies
9920 // also easier to manage all the guys this way
9921 9 guy::guy(zfix X,zfix Y,int32_t Id,int32_t Clk,bool mg) : enemy(X,Y,Id,Clk)
9922 9 {
9923 3 mainguy=mg;
9924 3 canfreeze=false;
9925 3 dir=down;
9926
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
9927 3 hxofs=2;
9928 3 hzsz=8;
9929 3 hxsz=12;
9930 3 hysz=17;
9931
9932
3/12
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
3 if(!superman && (!isdungeon() || id==gFAIRY || id==gFIRE || id==gZELDA))
9933 {
9934 3 superman = 1;
9935 3 hxofs=1000;
9936 3 }
9937 6 }
9938
9939 1381 bool guy::animate(int32_t index)
9940 {
9941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1381 times.
1381 if(switch_hooked) return enemy::animate(index);
9942
6/6
✓ Branch 0 taken 355 times.
✓ Branch 1 taken 1026 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 353 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
1381 if(mainguy && clk==0 && misc==0)
9943 {
9944 1 setupscreen();
9945 1 misc = 1;
9946 1 }
9947
9948
4/4
✓ Branch 0 taken 355 times.
✓ Branch 1 taken 1026 times.
✓ Branch 2 taken 354 times.
✓ Branch 3 taken 1 times.
1381 if(mainguy && fadeclk==0)
9949 1 return true;
9950
9951 1380 hp=256; // good guys never die...
9952
9953
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1380 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1380 if(hclk && !clk2)
9954 {
9955 // but if they get hit...
9956 ++clk2; // only do this once
9957
9958 if(!get_bit(quest_rules,qr_NOGUYFIRES))
9959 {
9960 addenemy(BSZ?64:72,68,eSHOOTFBALL,0);
9961 addenemy(BSZ?176:168,68,eSHOOTFBALL,0);
9962 }
9963 }
9964
9965 1380 return enemy::animate(index);
9966 1381 }
9967
9968 1381 void guy::draw(BITMAP *dest)
9969 {
9970 1381 update_enemy_frame();
9971
9972
6/6
✓ Branch 0 taken 355 times.
✓ Branch 1 taken 1026 times.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 289 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 33 times.
1381 if(!mainguy || fadeclk<0 || fadeclk&1)
9973 1348 enemy::draw(dest);
9974 1381 }
9975
9976 /*******************************/
9977 /********* Enemies *********/
9978 /*******************************/
9979
9980 eFire::eFire(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
9981 {
9982 clk4=0;
9983 shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
9984 // Spawn type
9985 if(flags & guy_fadeflicker)
9986 {
9987 clk=0;
9988 superman = 1;
9989 fading=fade_flicker;
9990 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
9991 dir=down;
9992
9993 if(!canmove(down,(zfix)8,spw_none,false))
9994 clk3=int32_t(13.0/step);
9995 }
9996 else if(flags & guy_fadeinstant)
9997 {
9998 clk=0;
9999 }
10000 SIZEflags = d->SIZEflags;
10001 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10002 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10003 // al_trace("Enemy txsz:%i\n", txsz);
10004 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10005 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10006 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10007 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10008 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10009 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10010 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10011 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10012 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10013 {
10014 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10015 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10016 }
10017
10018 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) d->zofs = (int32_t)zofs;
10019 }
10020
10021 bool eFire::animate(int32_t index)
10022 {
10023 if(switch_hooked) return enemy::animate(index);
10024 if(fallclk||drownclk) return enemy::animate(index);
10025 if(fading)
10026 {
10027 if(++clk4 > 60)
10028 {
10029 clk4=0;
10030 superman=0;
10031 fading=0;
10032
10033 if(flags2&cmbflag_armos && z==0 && fakez==0)
10034 removearmos(x,y);
10035
10036 clk2=0;
10037
10038 if(!canmove(down,(zfix)8,spw_none,false))
10039 {
10040 dir=0;
10041 y = y.getInt() & 0xF0;
10042 }
10043
10044 return Dead(index);
10045 }
10046 else if(flags2&cmbflag_armos && z==0 && fakez==0 && clk==0)
10047 removearmos(x,y);
10048 }
10049
10050 return enemy::animate(index);
10051 }
10052
10053 void eFire::draw(BITMAP *dest)
10054 {
10055 update_enemy_frame();
10056 enemy::draw(dest);
10057 }
10058
10059 int32_t eFire::takehit(weapon *w)
10060 {
10061 int32_t wpnId = w->id;
10062 int32_t wpnDir = w->dir;
10063
10064 if(wpnId==wHammer && shield && (flags & guy_bkshield)
10065 && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
10066 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
10067 {
10068 shield = false;
10069 flags &= ~(inv_left|inv_right|inv_back|inv_front);
10070
10071 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10072 o_tile=s_tile;
10073 }
10074
10075 int32_t ret = enemy::takehit(w);
10076 return ret;
10077 }
10078
10079 void eFire::break_shield()
10080 {
10081 if(!shield)
10082 return;
10083
10084 flags&=~(inv_front | inv_back | inv_left | inv_right);
10085 shield=false;
10086
10087 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10088 o_tile=s_tile;
10089 }
10090
10091 eOther::eOther(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10092 {
10093 //zprint2("npct other::other\n");
10094 clk4=0;
10095 shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
10096
10097 // Spawn type
10098 if(flags & guy_fadeflicker)
10099 {
10100 clk=0;
10101 superman = 1;
10102 fading=fade_flicker;
10103 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
10104 dir=down;
10105
10106 if(!canmove(down,(zfix)8,spw_none,false))
10107 clk3=int32_t(13.0/step);
10108 }
10109 else if(flags & guy_fadeinstant)
10110 {
10111 clk=0;
10112 }
10113 SIZEflags = d->SIZEflags;
10114 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10115 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10116 // al_trace("Enemy txsz:%i\n", txsz);
10117 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10118 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10119 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10120 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10121 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10122 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10123 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10124 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10125 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10126 {
10127 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10128 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10129 }
10130
10131 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
10132 }
10133
10134 bool eOther::animate(int32_t index)
10135 {
10136 if(switch_hooked) return enemy::animate(index);
10137 if(fallclk||drownclk) return enemy::animate(index);
10138 //zprint2("npct other::animate\n");
10139 if(fading)
10140 {
10141 if(++clk4 > 60)
10142 {
10143 clk4=0;
10144 superman=0;
10145 fading=0;
10146
10147 if(flags2&cmbflag_armos && z==0 && fakez==0)
10148 removearmos(x,y);
10149
10150 clk2=0;
10151
10152 if(!canmove(down,(zfix)8,spw_none,false))
10153 {
10154 dir=0;
10155 y = y.getInt() & 0xF0;
10156 }
10157
10158 return Dead(index);
10159 }
10160 else if(flags2&cmbflag_armos && z==0 && fakez==0 && clk==0)
10161 removearmos(x,y);
10162 }
10163
10164 return enemy::animate(index);
10165 }
10166
10167 void eOther::draw(BITMAP *dest)
10168 {
10169 update_enemy_frame();
10170 enemy::draw(dest);
10171 }
10172
10173 int32_t eOther::takehit(weapon *w)
10174 {
10175 int32_t wpnId = w->id;
10176 int32_t wpnDir = w->dir;
10177
10178 if(wpnId==wHammer && shield && (flags & guy_bkshield)
10179 && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
10180 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
10181 {
10182 shield = false;
10183 flags &= ~(inv_left|inv_right|inv_back|inv_front);
10184
10185 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10186 o_tile=s_tile;
10187 }
10188
10189 int32_t ret = enemy::takehit(w);
10190 return ret;
10191 }
10192
10193 void eOther::break_shield()
10194 {
10195 if(!shield)
10196 return;
10197
10198 flags&=~(inv_front | inv_back | inv_left | inv_right);
10199 shield=false;
10200
10201 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10202 o_tile=s_tile;
10203 }
10204
10205
10206 eScript::eScript(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10207 {
10208 clk4=0;
10209 shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
10210
10211 // Spawn type
10212 if(flags & guy_fadeflicker)
10213 {
10214 clk=0;
10215 superman = 1;
10216 fading=fade_flicker;
10217 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
10218 dir=down;
10219
10220 if(!canmove(down,(zfix)8,spw_none,false))
10221 clk3=int32_t(13.0/step);
10222 }
10223 else if(flags & guy_fadeinstant)
10224 {
10225 clk=0;
10226 }
10227 SIZEflags = d->SIZEflags;
10228 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10229 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10230 // al_trace("Enemy txsz:%i\n", txsz);
10231 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10232 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10233 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10234 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10235 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10236 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10237 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10238 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10239 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10240 {
10241 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10242 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10243 }
10244
10245 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
10246 }
10247
10248 bool eScript::animate(int32_t index)
10249 {
10250 if(switch_hooked) return enemy::animate(index);
10251 if(fallclk||drownclk) return enemy::animate(index);
10252 if(fading)
10253 {
10254 if(++clk4 > 60)
10255 {
10256 clk4=0;
10257 superman=0;
10258 fading=0;
10259
10260 if(flags2&cmbflag_armos && z==0 && fakez==0)
10261 removearmos(x,y);
10262
10263 clk2=0;
10264
10265 if(!canmove(down,(zfix)8,spw_none,false))
10266 {
10267 dir=0;
10268 y = y.getInt() & 0xF0;
10269 }
10270
10271 return Dead(index);
10272 }
10273 else if(flags2&cmbflag_armos && z==0 && fakez==0 && clk==0)
10274 removearmos(x,y);
10275 }
10276
10277 return enemy::animate(index);
10278 }
10279
10280 void eScript::draw(BITMAP *dest)
10281 {
10282 update_enemy_frame();
10283 enemy::draw(dest);
10284 }
10285
10286 int32_t eScript::takehit(weapon *w)
10287 {
10288 int32_t wpnId = w->id;
10289 int32_t wpnDir = w->dir;
10290
10291 if(wpnId==wHammer && shield && (flags & guy_bkshield)
10292 && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
10293 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
10294 {
10295 shield = false;
10296 flags &= ~(inv_left|inv_right|inv_back|inv_front);
10297
10298 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10299 o_tile=s_tile;
10300 }
10301
10302 int32_t ret = enemy::takehit(w);
10303 return ret;
10304 }
10305
10306 void eScript::break_shield()
10307 {
10308 if(!shield)
10309 return;
10310
10311 flags&=~(inv_front | inv_back | inv_left | inv_right);
10312 shield=false;
10313
10314 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10315 o_tile=s_tile;
10316 }
10317
10318
10319 eFriendly::eFriendly(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10320 {
10321 clk4=0;
10322 hyofs = -32768; //No hitbox initially.
10323 shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
10324
10325 // Spawn type
10326 if(flags & guy_fadeflicker)
10327 {
10328 clk=0;
10329 superman = 1;
10330 fading=fade_flicker;
10331 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
10332 dir=down;
10333
10334 if(!canmove(down,(zfix)8,spw_none,false))
10335 clk3=int32_t(13.0/step);
10336 }
10337 else if(flags & guy_fadeinstant)
10338 {
10339 clk=0;
10340 }
10341 SIZEflags = d->SIZEflags;
10342 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10343 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10344 // al_trace("Enemy txsz:%i\n", txsz);
10345 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10346 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10347 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10348 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10349 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10350 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10351 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10352 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10353 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10354 {
10355 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10356 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10357 }
10358
10359 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
10360 }
10361
10362 bool eFriendly::animate(int32_t index)
10363 {
10364 if(switch_hooked) return enemy::animate(index);
10365 if(fallclk||drownclk) return enemy::animate(index);
10366 if(fading)
10367 {
10368 if(++clk4 > 60)
10369 {
10370 clk4=0;
10371 superman=0;
10372 fading=0;
10373
10374 if(flags2&cmbflag_armos && z==0 && fakez==0)
10375 removearmos(x,y);
10376
10377 clk2=0;
10378
10379 if(!canmove(down,(zfix)8,spw_none,false))
10380 {
10381 dir=0;
10382 y = y.getInt() & 0xF0;
10383 }
10384
10385 return Dead(index);
10386 }
10387 else if(flags2&cmbflag_armos && z==0 && fakez==0 && clk==0)
10388 removearmos(x,y);
10389 }
10390
10391 return enemy::animate(index);
10392 }
10393
10394 void eFriendly::draw(BITMAP *dest)
10395 {
10396 update_enemy_frame();
10397 enemy::draw(dest);
10398 }
10399
10400 int32_t eFriendly::takehit(weapon *w)
10401 {
10402 int32_t wpnId = w->id;
10403 int32_t wpnDir = w->dir;
10404
10405 if(wpnId==wHammer && shield && (flags & guy_bkshield)
10406 && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
10407 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
10408 {
10409 shield = false;
10410 flags &= ~(inv_left|inv_right|inv_back|inv_front);
10411
10412 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10413 o_tile=s_tile;
10414 }
10415
10416 int32_t ret = enemy::takehit(w);
10417 return ret;
10418 }
10419
10420 void eFriendly::break_shield()
10421 {
10422 if(!shield)
10423 return;
10424
10425 flags&=~(inv_front | inv_back | inv_left | inv_right);
10426 shield=false;
10427
10428 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
10429 o_tile=s_tile;
10430 }
10431
10432
10433 23 void enemy::removearmos(int32_t ax,int32_t ay)
10434 {
10435
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if(did_armos)
10436 {
10437 23 return;
10438 }
10439
10440 did_armos=true;
10441 ax&=0xF0;
10442 ay&=0xF0;
10443 int32_t cd = (ax>>4)+ay;
10444 int32_t f = MAPFLAG(ax,ay);
10445 int32_t f2 = MAPCOMBOFLAG(ax,ay);
10446
10447 if(combobuf[tmpscr->data[cd]].type!=cARMOS)
10448 {
10449 return;
10450 }
10451
10452 tmpscr->data[cd] = tmpscr->undercombo;
10453 tmpscr->cset[cd] = tmpscr->undercset;
10454 tmpscr->sflag[cd] = 0;
10455
10456 if(f == mfARMOS_SECRET || f2 == mfARMOS_SECRET)
10457 {
10458 tmpscr->data[cd] = tmpscr->secretcombo[sSTAIRS];
10459 tmpscr->cset[cd] = tmpscr->secretcset[sSTAIRS];
10460 tmpscr->sflag[cd]=tmpscr->secretflag[sSTAIRS];
10461 sfx(tmpscr->secretsfx);
10462 }
10463
10464 if(f == mfARMOS_ITEM || f2 == mfARMOS_ITEM)
10465 {
10466 if(!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN))
10467 {
10468 additem(ax,ay,tmpscr->catchall, (ipONETIME2 + ipBIGRANGE) | ((tmpscr->flags3&fHOLDITEM) ? ipHOLDUP : 0) | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0));
10469 sfx(tmpscr->secretsfx);
10470 }
10471 }
10472
10473 putcombo(scrollbuf,ax,ay,tmpscr->data[cd],tmpscr->cset[cd]);
10474 23 }
10475
10476 eGhini::eGhini(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10477 {
10478 fading=fade_flicker;
10479 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
10480 dir=12;
10481 movestatus=1;
10482 step=0;
10483 clk=0;
10484 clk4=0;
10485 SIZEflags = d->SIZEflags;
10486 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10487 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10488 // al_trace("Enemy txsz:%i\n", txsz);
10489 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10490 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10491 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10492 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10493 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10494 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10495 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10496 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10497 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10498 {
10499 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10500 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10501 }
10502
10503 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
10504 }
10505
10506 bool eGhini::animate(int32_t index)
10507 {
10508 if(switch_hooked) return enemy::animate(index);
10509 if(fallclk||drownclk) return enemy::animate(index);
10510 if(dying)
10511 return Dead(index);
10512
10513 if(dmisc1)
10514 {
10515 if(misc)
10516 {
10517 if(clk4>160)
10518 misc=2;
10519
10520 floater_walk((misc==1)?0:rate,hrate,zslongToFix(dstep*100),zslongToFix(dstep*10),10,dmisc16,dmisc17); //120,10);
10521 removearmos(x,y);
10522 }
10523 else if(clk4>=60)
10524 {
10525 misc=1;
10526 clk3=32;
10527 fading=0;
10528 guygrid[(int32_t(y)&0xF0)+(int32_t(x)>>4)]=0;
10529 removearmos(x,y);
10530 }
10531 }
10532
10533 clk4++;
10534
10535 return enemy::animate(index);
10536 }
10537
10538 void eGhini::draw(BITMAP *dest)
10539 {
10540 update_enemy_frame();
10541 enemy::draw(dest);
10542 }
10543
10544 void eGhini::kickbucket()
10545 {
10546 hp=-1000; // don't call death_sfx()
10547 }
10548
10549
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
16 eTektite::eTektite(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10550 12 {
10551
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 old_y=y;
10552 4 dir=down;
10553 4 misc=1;
10554 4 clk=-15;
10555
10556
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(!BSZ)
10557
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 clk*=zc_oldrand()%3+1;
10558
10559 // avoid divide by 0 errors
10560
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(dmisc1 == 0)
10561 dmisc1 = 24;
10562
10563
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(dmisc2 == 0)
10564 dmisc2 = 3;
10565
10566 //nets+760;
10567 4 SIZEflags = d->SIZEflags;
10568
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10569 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10570 // al_trace("Enemy txsz:%i\n", txsz);
10571
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10572
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10573
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10574
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10575
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10576
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10577 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10578
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10580 {
10581 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10582 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10583 }
10584
10585
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
10586 8 }
10587
10588 1036 bool eTektite::animate(int32_t index)
10589 {
10590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1036 times.
1036 if(switch_hooked) return enemy::animate(index);
10591
2/4
✓ Branch 0 taken 1036 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1036 times.
1036 if(fallclk||drownclk) return enemy::animate(index);
10592
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 982 times.
1036 if(dying)
10593 54 return Dead(index);
10594
10595
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 23 times.
982 if(clk==0)
10596 {
10597 23 removearmos(x,y);
10598 23 }
10599
10600
1/2
✓ Branch 0 taken 982 times.
✗ Branch 1 not taken.
982 if(get_bit(quest_rules,qr_ENEMIESZAXIS))
10601 {
10602 y=floor_y;
10603 }
10604
10605
5/10
✓ Branch 0 taken 877 times.
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 877 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 877 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 877 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
982 if(clk>=0 && !stunclk && !frozenclock && (!watch || misc==0))
10606 {
10607
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
✓ Branch 2 taken 328 times.
✓ Branch 3 taken 412 times.
877 switch(misc)
10608 {
10609 case 0: // normal
10610
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 11 times.
137 if(!(zc_oldrand()%dmisc1))
10611 {
10612 11 misc=1;
10613 11 clk2=32;
10614 11 }
10615
10616 137 break;
10617
10618 case 1: // waiting to pounce
10619
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 19 times.
328 if(--clk2<=0)
10620 {
10621 19 int32_t r=zc_oldrand();
10622 19 misc=2;
10623 19 step=0-(zslongToFix(dstep*100)); // initial speed
10624 19 clk3=(r&1)+2; // left or right
10625 19 clk2start=clk2=(r&31)+10; // flight time
10626
10627
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if(y<32) clk2+=2; // make them come down from top of screen
10628
10629
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
19 if(y>112) clk2-=2; // make them go back up
10630
10631 19 cstart=c = 9-((r&31)>>3); // time before gravity kicks in
10632 19 }
10633
10634 328 break;
10635
10636 case 2: // in flight
10637 412 move(step);
10638
10639
2/2
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 230 times.
412 if(step>0) //going down
10640 {
10641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182 times.
182 if(COMBOTYPE(x+8,y+16)==cNOJUMPZONE)
10642 {
10643 step=0-step;
10644 }
10645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182 times.
182 else if(COMBOTYPE(x+8,y+16)==cNOENEMY)
10646 {
10647 step=0-step;
10648 }
10649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182 times.
182 else if(ispitfall(x+8,y+16))
10650 {
10651 step=0-step;
10652 }
10653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182 times.
182 else if(MAPFLAG(x+8,y+16)==mfNOENEMY)
10654 {
10655 step=0-step;
10656 }
10657
1/2
✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
182 else if(MAPCOMBOFLAG(x+8,y+16)==mfNOENEMY)
10658 {
10659 step=0-step;
10660 }
10661 182 }
10662
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 217 times.
230 else if(step<0)
10663 {
10664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 217 times.
217 if(COMBOTYPE(x+8,y)==cNOJUMPZONE)
10665 {
10666 step=0-step;
10667 }
10668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 217 times.
217 else if(COMBOTYPE(x+8,y)==cNOENEMY)
10669 {
10670 step=0-step;
10671 }
10672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 217 times.
217 else if(ispitfall(x+8,y))
10673 {
10674 step=0-step;
10675 }
10676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 217 times.
217 else if(MAPFLAG(x+8,y)==mfNOENEMY)
10677 {
10678 step=0-step;
10679 }
10680
1/2
✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
217 else if(MAPCOMBOFLAG(x+8,y)==mfNOENEMY)
10681 {
10682 step=0-step;
10683 }
10684 217 }
10685
10686
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 264 times.
412 if(clk3==left)
10687 {
10688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 if(COMBOTYPE(x,y+8)==cNOJUMPZONE)
10689 {
10690 clk3^=1;
10691 }
10692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 else if(COMBOTYPE(x,y+8)==cNOENEMY)
10693 {
10694 clk3^=1;
10695 }
10696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 else if(ispitfall(x,y+8))
10697 {
10698 clk3^=1;
10699 }
10700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148 times.
148 else if(MAPFLAG(x,y+8)==mfNOENEMY)
10701 {
10702 clk3^=1;
10703 }
10704
1/2
✓ Branch 0 taken 148 times.
✗ Branch 1 not taken.
148 else if(MAPCOMBOFLAG(x,y+8)==mfNOENEMY)
10705 {
10706 clk3^=1;
10707 }
10708 148 }
10709 else
10710 {
10711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
264 if(COMBOTYPE(x+16,y+8)==cNOJUMPZONE)
10712 {
10713 clk3^=1;
10714 }
10715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
264 else if(COMBOTYPE(x+16,y+8)==cNOENEMY)
10716 {
10717 clk3^=1;
10718 }
10719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
264 else if(ispitfall(x+16,y+8))
10720 {
10721 clk3^=1;
10722 }
10723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 264 times.
264 else if(MAPFLAG(x+16,y+8)==mfNOENEMY)
10724 {
10725 clk3^=1;
10726 }
10727
1/2
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
264 else if(MAPCOMBOFLAG(x+16,y+8)==mfNOENEMY)
10728 {
10729 clk3^=1;
10730 }
10731 }
10732
10733 412 --c;
10734
10735
4/4
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 271 times.
✓ Branch 2 taken 271 times.
✓ Branch 3 taken 141 times.
412 if(c<0 && step<zslongToFix(dstep*100))
10736 {
10737 141 step+=zslongToFix(dmisc3*100);
10738 141 }
10739
10740 412 int32_t nb=get_bit(quest_rules,qr_NOBORDER) ? 16 : 0;
10741
10742
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 1 times.
412 if(x<=16-nb) clk3=right;
10743
10744
1/2
✓ Branch 0 taken 412 times.
✗ Branch 1 not taken.
412 if(x>=224+nb) clk3=left;
10745
10746 412 x += (clk3==left) ? -1 : 1;
10747
10748
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 397 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 395 times.
412 if((--clk2<=0 && y>=16-nb) || y>=144+nb)
10749 {
10750
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
17 if(y>=144+nb && get_bit(quest_rules,qr_ENEMIESZAXIS))
10751 {
10752 step=0-step;
10753 y--;
10754 }
10755
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
17 else if(zc_oldrand()%dmisc2) //land and wait
10756 {
10757 11 clk=misc=0;
10758 11 } //land and jump again
10759 else
10760 {
10761 6 misc=1;
10762 6 clk2=0;
10763 }
10764 17 }
10765
10766 412 break;
10767 } // switch
10768 877 }
10769
10770
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
982 if(get_bit(quest_rules,qr_ENEMIESZAXIS) && misc==2)
10771 {
10772 if (moveflags & FLAG_USE_FAKE_Z)
10773 {
10774 int32_t tempy = floor_y;
10775 fakez=zc_max(0,zc_min(clk2start-clk2,clk2));
10776 floor_y = y;
10777 y=tempy-fakez;
10778 old_y = y;
10779 }
10780 else
10781 {
10782 int32_t tempy = floor_y;
10783 z=zc_max(0,zc_min(clk2start-clk2,clk2));
10784 floor_y = y;
10785 y=tempy-z;
10786 old_y = y;
10787 }
10788 }
10789
10790
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 982 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
982 if(stunclk && (clk&31)==1)
10791 clk=0;
10792
10793 982 return enemy::animate(index);
10794 1036 }
10795
10796 void eTektite::drawshadow(BITMAP *dest,bool translucent)
10797 {
10798 if(z<1 && fakez<1 && get_bit(quest_rules,qr_ENEMIESZAXIS))
10799 return;
10800
10801 int32_t tempy=yofs;
10802 int32_t fdiv = frate/4;
10803 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
10804 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
10805 efrate:((clk>=(frate>>1))?1:0);
10806 flip = 0;
10807 shadowtile = wpnsbuf[spr_shadow].tile;
10808
10809 if(get_bit(quest_rules,qr_NEWENEMYTILES))
10810 {
10811 if(misc==0)
10812 {
10813 shadowtile+=f2;
10814 }
10815 else if(misc!=1)
10816 shadowtile+=2;
10817 }
10818 else
10819 {
10820 if(misc==0)
10821 {
10822 shadowtile += f2 ? 1 : 0;
10823 }
10824 else if(misc!=1)
10825 {
10826 ++shadowtile;
10827 }
10828 }
10829
10830 yofs+=8;
10831
10832 if(!get_bit(quest_rules,qr_ENEMIESZAXIS) && misc==2)
10833 {
10834 yofs+=zc_max(0,zc_min(clk2start-clk2,clk2));
10835 }
10836 if(!shadow_overpit(this))
10837 enemy::drawshadow(dest,translucent);
10838 yofs=tempy;
10839 }
10840
10841 1037 void eTektite::draw(BITMAP *dest)
10842 {
10843 1037 update_enemy_frame();
10844 1037 enemy::draw(dest);
10845 1037 }
10846
10847 eItemFairy::eItemFairy(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10848 {
10849 step=zslongToFix(guysbuf[id&0xFFF].step*100);
10850 superman=1;
10851 dir=8;
10852 hxofs=1000;
10853 mainguy=false;
10854 count_enemy=false;
10855 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10856 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10857 // al_trace("Enemy txsz:%i\n", txsz);
10858 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = tysz; if ( tysz > 1 ) extend = 3; }
10859 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = hxsz;
10860 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = hysz;
10861 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = hzsz;
10862 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = hxofs;
10863 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = hyofs;
10864 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10865 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)xofs;
10866 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10867 {
10868 yofs = (int32_t)yofs; //This seems to be setting to +48 or something with any value set?! -Z
10869 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10870 }
10871
10872 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)zofs;
10873 }
10874
10875 bool eItemFairy::animate(int32_t index)
10876 {
10877 if(switch_hooked) return enemy::animate(index);
10878 if(dying)
10879 return Dead(index);
10880
10881 //if(clk>32)
10882 misc=1;
10883 bool w=watch;
10884 watch=false;
10885 variable_walk_8(misc?3:0,0,8,spw_floater);
10886 watch=w;
10887
10888 if(clk==0)
10889 {
10890 removearmos(x,y);
10891 }
10892
10893 return enemy::animate(index);
10894 }
10895
10896 void eItemFairy::draw(BITMAP *dest)
10897 {
10898 //these are here to bypass compiler warnings about unused arguments
10899 dest=dest;
10900 }
10901
10902 ePeahat::ePeahat(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
10903 {
10904 //floater_walk(int32_t rate,int32_t newclk,zfix ms,zfix ss,int32_t s,int32_t p, int32_t g)
10905 floater_walk(misc?rate:0, hrate, zslongToFix(dstep*100),zslongToFix(dstep*10), 10, dmisc16,dmisc17); // 80, 16);
10906 dir=8;
10907 movestatus=1;
10908 clk=0;
10909 step=0;
10910 //nets+720;
10911 SIZEflags = d->SIZEflags;
10912 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
10913 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
10914 // al_trace("Enemy txsz:%i\n", txsz);
10915 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
10916 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
10917 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
10918 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
10919 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
10920 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
10921 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
10922 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
10923 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
10924 {
10925 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
10926 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
10927 }
10928
10929 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
10930 }
10931
10932 bool ePeahat::animate(int32_t index)
10933 {
10934 if(switch_hooked) return enemy::animate(index);
10935 if(fallclk||drownclk) return enemy::animate(index);
10936 if(slide())
10937 {
10938 return false;
10939 }
10940
10941 if(dying)
10942 return Dead(index);
10943
10944 if(clk==0)
10945 {
10946 removearmos(x,y);
10947 }
10948
10949 if(stunclk==0 && clk>96)
10950 misc=1;
10951
10952 if(!watch)
10953 floater_walk(misc?rate:0, hrate, zslongToFix(dstep*100),zslongToFix(dstep*10), 10, 80, 16);
10954
10955 if(get_bit(quest_rules,qr_ENEMIESZAXIS) && !(isSideViewGravity()))
10956 {
10957 if (moveflags & FLAG_USE_FAKE_Z) fakez=int32_t(step*1.1/((zslongToFix(dstep*10))*1.1));
10958 else z=int32_t(step*1.1/((zslongToFix(dstep*10))*1.1));
10959 }
10960
10961 if(watch && get_bit(quest_rules,qr_PEAHATCLOCKVULN))
10962 superman=0;
10963 else
10964 superman=(movestatus && !get_bit(quest_rules,qr_ENEMIESZAXIS)) ? 1 : 0;
10965 //stunclk=0; //Not sure what was going on here, or what was intended. Why was this set to 0? -Z
10966 if ( FFCore.getQuestHeaderInfo(vZelda) >= 0x250 )
10967 {
10968 if ( stunclk ) --stunclk;
10969 }
10970 else stunclk = 0; //Was probably this way in 2.10 quests. if not, then we never need to clear it. -Z
10971 //Pretty sure this was always an error. -Z ( 14FEB2019 )
10972
10973
10974 if(x<16) dir=right; //this is ugly, but so is moving or creating these guys with scripts.
10975
10976 return enemy::animate(index);
10977 }
10978
10979 void ePeahat::drawshadow(BITMAP *dest, bool translucent)
10980 {
10981 int32_t tempy=yofs;
10982 flip = 0;
10983 shadowtile = wpnsbuf[spr_shadow].tile+posframe;
10984
10985 if(!get_bit(quest_rules,qr_ENEMIESZAXIS))
10986 {
10987 yofs+=8;
10988 yofs+=int32_t(step/zslongToFix(dstep*10));
10989 }
10990 if(!shadow_overpit(this))
10991 enemy::drawshadow(dest,translucent);
10992 yofs=tempy;
10993 }
10994
10995 void ePeahat::draw(BITMAP *dest)
10996 {
10997 update_enemy_frame();
10998 enemy::draw(dest);
10999 }
11000
11001 int32_t ePeahat::takehit(weapon *w)
11002 {
11003 int32_t wpnId = w->id;
11004 int32_t enemyHitWeapon = w->parentitem;
11005
11006 if(dying || clk<0 || hclk>0)
11007 return 0;
11008
11009 if(superman && !(wpnId==wSBomb) // vulnerable to super bombs
11010 // fire boomerang, for nailing peahats
11011 && !(wpnId==wBrang && (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))>0))
11012 return 0;
11013
11014 // Time for a kludge...
11015 int32_t s = superman;
11016 superman = 0;
11017 int32_t ret = enemy::takehit(w);
11018 superman = s;
11019
11020 // Anyway...
11021 if(stunclk == 160)
11022 {
11023 clk2=0;
11024 movestatus=0;
11025 misc=0;
11026 clk=0;
11027 step=0;
11028 }
11029
11030 return ret;
11031 }
11032
11033 // auomatically kill off enemy (for rooms with ringleaders)
11034 void ePeahat::kickbucket()
11035 {
11036 hp=-1000; // don't call death_sfx()
11037 }
11038
11039 eLeever::eLeever(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
11040 {
11041 // if(d->misc1==0) { misc=-1; clk-=16; } //Line of Sight leevers
11042 if(dmisc1==0)
11043 {
11044 misc=-1; //Line of Sight leevers
11045 clk-=16;
11046 }
11047 clk3 = 0;
11048 //nets+1460;
11049 temprule=(get_bit(quest_rules,qr_NEWENEMYTILES)) != 0;
11050 submerged = false;
11051 SIZEflags = d->SIZEflags;
11052 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
11053 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
11054 // al_trace("Enemy txsz:%i\n", txsz);
11055 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
11056 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
11057 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
11058 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
11059 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
11060 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
11061 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
11062 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
11063 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
11064 {
11065 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
11066 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
11067 }
11068
11069 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
11070 }
11071
11072 bool eLeever::isSubmerged() const
11073 {
11074 Z_scripterrlog("misc is: %d\n", misc);
11075 return misc <= 0;
11076
11077 }
11078
11079 bool eLeever::animate(int32_t index)
11080 {
11081 if(switch_hooked) return enemy::animate(index);
11082 if(fallclk||drownclk)
11083 {
11084 return enemy::animate(index);
11085 }
11086 if(dying)
11087 return Dead(index);
11088
11089 if(clk==0)
11090 {
11091 removearmos(x,y);
11092 }
11093
11094 if(clk>=0 && !slide())
11095 {
11096 // switch(d->misc1)
11097 switch(dmisc1)
11098 {
11099 case 0: //line of sight
11100 case 2:
11101 switch(misc) //is this leever active
11102 {
11103 case -1: //submerged
11104 {
11105 if (!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk)) misc = 0;
11106 if((dmisc1==2)&&(zc_oldrand()&255))
11107 {
11108 break;
11109 }
11110
11111 int32_t active=0;
11112
11113 for(int32_t i=0; i<guys.Count(); i++)
11114 {
11115 if(guys.spr(i)->id==id && (((enemy*)guys.spr(i))->misc>=0))
11116 {
11117 ++active;
11118 }
11119 }
11120
11121 if(active<((dmisc1==2)?1:2))
11122 {
11123 misc=0; //activate this one
11124 clk3=1; //This needs to be set so that it knows that it's being emerged of it's own will and not because it got stunned.
11125 }
11126 }
11127 break;
11128
11129 case 0:
11130 {
11131
11132 if (!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk))
11133 {
11134 misc=1;
11135 clk2=0;
11136 }
11137 else if (clk3<=0)
11138 {
11139 misc = -1;
11140 break;
11141 }
11142 int32_t s=0;
11143
11144 for(int32_t i=0; i<guys.Count(); i++)
11145 {
11146 if(guys.spr(i)->id==id && ((enemy*)guys.spr(i))->misc==1)
11147 {
11148 ++s;
11149 }
11150 }
11151
11152 if(s>0)
11153 {
11154 break;
11155 }
11156
11157 int32_t d2=zc_oldrand()&1;
11158
11159 if(HeroDir()>=left)
11160 {
11161 d2+=2;
11162 }
11163
11164 if(canplace(d2) || canplace(d2^1))
11165 {
11166 misc=1;
11167 clk2=0;
11168 clk=0;
11169 }
11170 }
11171 break;
11172
11173 case 1:
11174
11175 if(++clk2>16||(!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk) && clk2>8)) misc=2;
11176
11177 break;
11178
11179 case 2:
11180
11181 if(++clk2>24||(!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk) && clk2>12)) misc=3;
11182
11183 break;
11184
11185 // case 3: if(stunclk) break; if(scored) dir^=1; if(!canmove(dir,false)) misc=4; else move((zfix)(d->step/100.0)); break;
11186 case 3:
11187
11188 if(stunclk || frozenclock || watch) break;
11189
11190 if(scored) dir^=1;
11191
11192 if(!canmove(dir,false)) misc=4;
11193 else move(zslongToFix(dstep*100));
11194
11195 break;
11196
11197 case 4:
11198 if (!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk)) misc = 2;
11199 if(--clk2<=16)
11200 {
11201 misc=5;
11202 clk=8;
11203 }
11204
11205 break;
11206
11207 case 5:
11208 if (!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk)) misc = 1;
11209 if(--clk2<=0) misc=((dmisc1==2)?-1:0);
11210
11211 break;
11212 } // switch(misc)
11213
11214 break;
11215
11216 default: //random
11217 // step=d->misc3/100.0;
11218
11219 step=zslongToFix(dmisc3*100);
11220 if (get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) || (!watch && !stunclk)) ++clk2;
11221 else if (!get_bit(quest_rules, qr_LEEVERS_DONT_OBEY_STUN) && (watch || stunclk))
11222 {
11223 if (clk2 < 48) clk2+=2;
11224 if (clk2 >= 300) clk2-=2;
11225 }
11226
11227 if(clk2<32) misc=1;
11228 else if(clk2<48) misc=2;
11229 else if(clk2<300)
11230 {
11231 /*if(misc==2 && (int32_t)(dmisc3*0.48)%8)
11232 {
11233 fix_coords();
11234 }*/
11235 misc=3;
11236 step = zslongToFix(dstep*100);
11237 }
11238 else if(clk2<316) misc=2;
11239 else if(clk2<412) misc=1;
11240 else if(clk2<540)
11241 {
11242 misc=0;
11243 step=0;
11244 }
11245 else clk2=0;
11246
11247 if(clk2==48) clk=0;
11248
11249 // variable_walk(d->rate, d->homing, 0);
11250 variable_walk(rate, homing, 0);
11251 } // switch(dmisc1)
11252 }
11253
11254 hxofs=(misc>=2)?0:1000;
11255 return enemy::animate(index);
11256 }
11257
11258 bool eLeever::canplace(int32_t d2)
11259 {
11260 int32_t nx=HeroX();
11261 int32_t ny=HeroY();
11262
11263 if(d2<left) ny&=0xF0;
11264 else nx&=0xF0;
11265
11266 switch(d2)
11267 {
11268 // case up: ny-=((d->misc1==0)?32:48); break;
11269 // case down: ny+=((d->misc1==0)?32:48); if(ny-HeroY()<32) ny+=((d->misc1==0)?16:0); break;
11270 // case left: nx-=((d->misc1==0)?32:48); break;
11271 // case right: nx+=((d->misc1==0)?32:48); if(nx-HeroX()<32) nx+=((d->misc1==0)?16:0); break;
11272 case up:
11273 ny-=((dmisc1==0||dmisc1==2)?32:48);
11274 break;
11275
11276 case down:
11277 ny+=((dmisc1==0||dmisc1==2)?32:48);
11278
11279 if(ny-HeroY()<32) ny+=((dmisc1==0||dmisc1==2)?16:0);
11280
11281 break;
11282
11283 case left:
11284 nx-=((dmisc1==0||dmisc1==2)?32:48);
11285 break;
11286
11287 case right:
11288 nx+=((dmisc1==0||dmisc1==2)?32:48);
11289
11290 if(nx-HeroX()<32) nx+=((dmisc1==0||dmisc1==2)?16:0);
11291
11292 break;
11293 }
11294
11295 if(m_walkflag(nx,ny,spw_halfstep, dir)||m_walkflag(nx,ny-8,spw_halfstep, dir)) /*none*/
11296 return false;
11297
11298 if(d2>=left)
11299 if(m_walkflag(HeroX(),HeroY(),spw_halfstep, dir)||m_walkflag(HeroX(),HeroY()-8,spw_halfstep, dir)) /*none*/
11300 return false;
11301
11302 x=nx;
11303 y=ny;
11304 dir=d2^1;
11305 return true;
11306 }
11307
11308 void eLeever::draw(BITMAP *dest)
11309 {
11310 // cs=d->cset;
11311 cs=dcset;
11312 update_enemy_frame();
11313 if(!fallclk&&!drownclk)
11314 {
11315 switch(misc)
11316 {
11317 case -1:
11318 case 0:
11319 return;
11320 }
11321 }
11322
11323 enemy::draw(dest);
11324 }
11325
11326 eWallM::eWallM(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
11327 {
11328 //zprint2("eWallM::eWallM\n");
11329 hashero=false;
11330 //nets+1000;
11331 SIZEflags = d->SIZEflags;
11332 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
11333 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
11334 // al_trace("Enemy txsz:%i\n", txsz);
11335 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
11336 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
11337 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
11338 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
11339 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
11340 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
11341 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
11342 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
11343 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
11344 {
11345 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
11346 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
11347 }
11348
11349 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
11350 }
11351
11352 bool eWallM::animate(int32_t index)
11353 {
11354 if(switch_hooked) return enemy::animate(index);
11355 if(fallclk||drownclk)
11356 {
11357 return enemy::animate(index);
11358 }
11359 if(dying)
11360 return Dead(index);
11361
11362 if(clk==0)
11363 {
11364 removearmos(x,y);
11365 }
11366
11367 hxofs=1000;
11368 if(misc==0) //inside wall, ready to spawn?
11369 {
11370 //zprint2("Wallmaster is ready to spawn, clk is: %d\n",clk);
11371 //zprint2("frame is: %d\n",frame);
11372 //zprint2("wallm_load_clk is: %d\n",wallm_load_clk);
11373 if(frame-wallm_load_clk>80 && clk>=0)
11374 {
11375 //zprint2("getting wall\n");
11376 int32_t wall=hero_on_wall();
11377 //zprint2("Wallmaster wall is %d\n",wall);
11378 int32_t wallm_cnt=0;
11379
11380 for(int32_t i=0; i<guys.Count(); i++)
11381 if(((enemy*)guys.spr(i))->family==eeWALLM)
11382 {
11383 int32_t m=((enemy*)guys.spr(i))->misc;
11384
11385 if(m && ((enemy*)guys.spr(i))->clk3==(wall^1))
11386 {
11387 ++wallm_cnt;
11388 }
11389 }
11390
11391 if(wall>0)
11392 {
11393 --wall;
11394 misc=1; //emerging from the wall?
11395 //zprint2("Wallmaster is emerging\n");
11396 clk2=0;
11397 clk3=wall^1;
11398 wallm_load_clk=frame;
11399
11400 if(wall<=down)
11401 {
11402 if(HeroDir()==left)
11403 dir=right;
11404 else
11405 dir=left;
11406 }
11407 else
11408 {
11409 if(HeroDir()==up)
11410 dir=down;
11411 else
11412 dir=up;
11413 }
11414
11415 switch(wall)
11416 {
11417 case up:
11418 y=0;
11419 break;
11420
11421 case down:
11422 y=160;
11423 break;
11424
11425 case left:
11426 x=0;
11427 break;
11428
11429 case right:
11430 x=240;
11431 break;
11432 }
11433
11434 //zprint2("Wallmaster (p1) x is %d\n",x);
11435 //zprint2("Wallmaster (p1) y is %d\n",y);
11436
11437 switch(dir)
11438 {
11439 case up:
11440 y=(HeroY()+48-(wallm_cnt&1)*12);
11441 flip=wall&1;
11442 break;
11443
11444 case down:
11445 y=(HeroY()-48+(wallm_cnt&1)*12);
11446 flip=((wall&1)^1)+2;
11447 break;
11448
11449 case left:
11450 x=(HeroX()+48-(wallm_cnt&1)*12);
11451 flip=(wall==up?2:0)+1;
11452 break;
11453
11454 case right:
11455 x=(HeroX()-48+(wallm_cnt&1)*12);
11456 flip=(wall==up?2:0);
11457 break;
11458 }
11459
11460 //zprint2("Wallmaster (p2) x is %d\n",x);
11461 //zprint2("Wallmaster (p2) y is %d\n",y);
11462 }
11463 }
11464 }
11465 else
11466 wallm_crawl();
11467
11468 return enemy::animate(index);
11469 }
11470
11471 void eWallM::wallm_crawl()
11472 {
11473 bool w=watch;
11474 hxofs=0;
11475
11476 if(slide())
11477 {
11478 return;
11479 }
11480
11481 // if(dying || watch || (!hashero && stunclk))
11482 if(dying || (!hashero && ( stunclk || frozenclock )))
11483 {
11484 return;
11485 }
11486
11487 watch=false;
11488 ++clk2;
11489 // Misc1: slightly different movement
11490 //zprint2("wallmaster crawl\n");
11491 //zprint2("wallmaster tmpdstep is %d\n",tmpdstep);
11492 float tmpmisc3 = ((40.0/(int32_t)dstep)*40);
11493
11494 //int32_t tmpmisc = int32_t((40.0/dstep)*40);
11495 //zprint2("wallmaster crawl tmpmisc is: %d\n", tmpmisc);
11496 //zprint2("wallmaster crawl tmpmisc4 is: %d\n", tmpmisc4);
11497 misc=(clk2/(dmisc1==1?40:(int32_t)tmpmisc3))+1;
11498 //zprint2("wallmaster crawl misc is: %d\n", misc);
11499 if(w&&misc>=3&&misc<=5)
11500 {
11501 --clk2;
11502 }
11503
11504 switch(misc)
11505 {
11506 case 1:
11507 case 2:
11508 zc_swap(dir,clk3);
11509 move(step);
11510 zc_swap(dir,clk3);
11511 break;
11512
11513 case 3:
11514 case 4:
11515 case 5:
11516 if(w)
11517 {
11518 watch=w;
11519 return;
11520 }
11521
11522 move(step);
11523 break;
11524
11525 case 6:
11526 case 7:
11527 zc_swap(dir,clk3);
11528 dir^=1;
11529 move(step);
11530 dir^=1;
11531 zc_swap(dir,clk3);
11532 break;
11533
11534 default:
11535 misc=0;
11536 break;
11537 }
11538
11539 watch=w;
11540 }
11541
11542 void eWallM::grabhero()
11543 {
11544 hashero=true;
11545 superman=1;
11546 }
11547
11548 void eWallM::draw(BITMAP *dest)
11549 {
11550 dummy_bool[1]=hashero;
11551 update_enemy_frame();
11552
11553 if(misc>0 || fallclk||drownclk)
11554 {
11555 masked_draw(dest,16,playing_field_offset+16,224,144);
11556 }
11557
11558 // enemy::draw(dest);
11559 // tile = clk&8 ? 128:129;
11560 }
11561
11562 bool eWallM::isSubmerged() const
11563 {
11564 return ( !misc );
11565 }
11566
11567 eTrap::eTrap(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
11568 {
11569 ox=x; //original x
11570 oy=y; //original y
11571 if(get_bit(quest_rules,qr_TRAPPOSFIX))
11572 {
11573 yofs = (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
11574 }
11575
11576 mainguy=false;
11577 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
11578 //nets+420;
11579 dummy_int[1]=0;
11580 SIZEflags = d->SIZEflags;
11581 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
11582 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
11583 // al_trace("Enemy txsz:%i\n", txsz);
11584 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
11585 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
11586 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
11587 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
11588 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
11589 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
11590 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
11591 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
11592 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
11593 {
11594 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
11595 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
11596 }
11597
11598 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
11599 }
11600
11601 bool eTrap::animate(int32_t index)
11602 {
11603 if(switch_hooked) return enemy::animate(index);
11604 if(fallclk||drownclk) return enemy::animate(index);
11605 if(clk<0)
11606 return enemy::animate(index);
11607
11608 if(clk==0)
11609 {
11610 removearmos(x,y);
11611 }
11612
11613 if(misc==0) // waiting
11614 {
11615 ox = x;
11616 oy = y;
11617 double _MSVC2022_tmp1, _MSVC2022_tmp2;
11618 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
11619
11620 if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
11621 {
11622 dir=down;
11623 }
11624 else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
11625 {
11626 dir=right;
11627 }
11628 else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4)))
11629 {
11630 dir=up;
11631 }
11632 else
11633 {
11634 dir=left;
11635 }
11636
11637 int32_t d2=lined_up(15,true);
11638
11639 if(((d2<left || d2 > right) && (dmisc1==1)) ||
11640 ((d2>down) && (dmisc1==2)) ||
11641 ((d2>right) && (!dmisc1)) ||
11642 ((d2<l_up) && (dmisc1==4)) ||
11643 ((d2!=r_up) && (d2!=l_down) && (dmisc1==6)) ||
11644 ((d2!=l_up) && (d2!=r_down) && (dmisc1==8)))
11645 {
11646 d2=-1;
11647 }
11648
11649 if(d2!=-1 && trapmove(d2))
11650 {
11651 dir=d2;
11652 misc=1;
11653 clk2=(dir==down)?3:0;
11654 }
11655 }
11656
11657 if(misc==1) // charging
11658 {
11659 clk2=(clk2+1)&3;
11660 step=(clk2==3)?1:2;
11661
11662 if(!trapmove(dir) || clip())
11663 {
11664 misc=2;
11665
11666 if(dir<l_up)
11667 {
11668 dir=dir^1;
11669 }
11670 else
11671 {
11672 dir=dir^3;
11673 }
11674 }
11675 else
11676 {
11677 sprite::move(step);
11678 }
11679 }
11680
11681 if(misc==2) // retreating
11682 {
11683 step=(++clk2&1)?1:0;
11684
11685 switch(dir)
11686 {
11687 case up:
11688 if(int32_t(y)<=oy) goto trap_rest;
11689 else sprite::move(step);
11690
11691 break;
11692
11693 case left:
11694 if(int32_t(x)<=ox) goto trap_rest;
11695 else sprite::move(step);
11696
11697 break;
11698
11699 case down:
11700 if(int32_t(y)>=oy) goto trap_rest;
11701 else sprite::move(step);
11702
11703 break;
11704
11705 case right:
11706 if(int32_t(x)>=ox) goto trap_rest;
11707 else sprite::move(step);
11708
11709 break;
11710
11711 case l_up:
11712 if(int32_t(x)<=ox && int32_t(y)<=oy) goto trap_rest;
11713 else sprite::move(step);
11714
11715 break;
11716
11717 case r_up:
11718 if(int32_t(x)>=ox && int32_t(y)<=oy) goto trap_rest;
11719 else sprite::move(step);
11720
11721 break;
11722
11723 case l_down:
11724 if(int32_t(x)<=ox && int32_t(y)>=oy) goto trap_rest;
11725 else sprite::move(step);
11726
11727 break;
11728
11729 case r_down:
11730 if(int32_t(x)>=ox && int32_t(y)>=oy) goto trap_rest;
11731 else sprite::move(step);
11732
11733 break;
11734 trap_rest:
11735 {
11736 x=ox;
11737 y=oy;
11738 misc=0;
11739 }
11740 }
11741 }
11742
11743 return enemy::animate(index);
11744 }
11745
11746 bool eTrap::trapmove(int32_t ndir)
11747 {
11748 if(get_bit(quest_rules,qr_MEANTRAPS))
11749 {
11750 if(tmpscr->flags2&fFLOATTRAPS)
11751 return canmove(ndir,(zfix)1,spw_floater, 0, 0, 15, 15,false);
11752
11753 return canmove(ndir,(zfix)1,spw_water, 0, 0, 15, 15,false);
11754 }
11755
11756 if(oy==80 && !(ndir==left || ndir == right))
11757 return false;
11758
11759 if(ox==128 && !(ndir==up || ndir==down))
11760 return false;
11761
11762 if(oy<80 && ndir==up)
11763 return false;
11764
11765 if(oy>80 && ndir==down)
11766 return false;
11767
11768 if(ox<128 && ndir==left)
11769 return false;
11770
11771 if(ox>128 && ndir==right)
11772 return false;
11773
11774 if(ox<128 && oy<80 && ndir==l_up)
11775 return false;
11776
11777 if(ox<128 && oy>80 && ndir==l_down)
11778 return false;
11779
11780 if(ox>128 && oy<80 && ndir==r_up)
11781 return false;
11782
11783 if(ox>128 && oy>80 && ndir==r_down)
11784 return false;
11785
11786 return true;
11787 }
11788
11789 bool eTrap::clip()
11790 {
11791 if(get_bit(quest_rules,qr_MEANPLACEDTRAPS))
11792 {
11793 switch(dir)
11794 {
11795 case up:
11796 if(y<=0) return true;
11797
11798 break;
11799
11800 case down:
11801 if(y>=160) return true;
11802
11803 break;
11804
11805 case left:
11806 if(x<=0) return true;
11807
11808 break;
11809
11810 case right:
11811 if(x>=240) return true;
11812
11813 break;
11814
11815 case l_up:
11816 if(y<=0||x<=0) return true;
11817
11818 break;
11819
11820 case l_down:
11821 if(y>=160||x<=0) return true;
11822
11823 break;
11824
11825 case r_up:
11826 if(y<=0||x>=240) return true;
11827
11828 break;
11829
11830 case r_down:
11831 if(y>=160||x>=240) return true;
11832
11833 break;
11834 }
11835
11836 return false;
11837 }
11838 else
11839 {
11840 switch(dir)
11841 {
11842 case up:
11843 if(oy>80 && y<=86) return true;
11844
11845 break;
11846
11847 case down:
11848 if(oy<80 && y>=80) return true;
11849
11850 break;
11851
11852 case left:
11853 if(ox>128 && x<=124) return true;
11854
11855 break;
11856
11857 case right:
11858 if(ox<120 && x>=116) return true;
11859
11860 break;
11861
11862 case l_up:
11863 if(oy>80 && y<=86 && ox>128 && x<=124) return true;
11864
11865 break;
11866
11867 case l_down:
11868 if(oy<80 && y>=80 && ox>128 && x<=124) return true;
11869
11870 break;
11871
11872 case r_up:
11873 if(oy>80 && y<=86 && ox<120 && x>=116) return true;
11874
11875 break;
11876
11877 case r_down:
11878 if(oy<80 && y>=80 && ox<120 && x>=116) return true;
11879
11880 break;
11881 }
11882
11883 return false;
11884 }
11885 }
11886
11887 void eTrap::draw(BITMAP *dest)
11888 {
11889 update_enemy_frame();
11890 enemy::draw(dest);
11891 }
11892
11893 int32_t eTrap::takehit(weapon*)
11894 {
11895 return 0;
11896 }
11897
11898 eTrap2::eTrap2(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
11899 {
11900 lasthit=-1;
11901 lasthitclk=0;
11902 mainguy=false;
11903 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
11904 step=2;
11905 if(dmisc1==1 || (dmisc1==0 && zc_oldrand()&2))
11906 {
11907 dir=(x<=112)?right:left;
11908 }
11909 else
11910 {
11911 dir=(y<=72)?down:up;
11912 }
11913
11914 if(get_bit(quest_rules,qr_TRAPPOSFIX))
11915 {
11916 yofs = (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
11917 }
11918
11919 //nets+((id==eTRAP_LR)?540:520);
11920 dummy_int[1]=0;
11921 SIZEflags = d->SIZEflags;
11922 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
11923 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
11924 // al_trace("Enemy txsz:%i\n", txsz);
11925 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
11926 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
11927 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
11928 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
11929 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
11930 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
11931 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
11932 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
11933 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
11934 {
11935 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
11936 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
11937 }
11938
11939 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
11940 }
11941
11942 bool eTrap2::animate(int32_t index)
11943 {
11944 if(switch_hooked) return enemy::animate(index);
11945 if(fallclk||drownclk) return enemy::animate(index);
11946 if(clk<0)
11947 return enemy::animate(index);
11948
11949 if(clk==0)
11950 {
11951 removearmos(x,y);
11952 }
11953
11954 if(!get_bit(quest_rules,qr_PHANTOMPLACEDTRAPS))
11955 {
11956 if(lasthitclk>0)
11957 {
11958 --lasthitclk;
11959 }
11960 else
11961 {
11962 lasthit=-1;
11963 }
11964
11965 bool hitenemy=false;
11966
11967 for(int32_t j=0; j<guys.Count(); j++)
11968 {
11969 if((j!=index) && (lasthit!=j))
11970 {
11971 if(hit(guys.spr(j)))
11972 {
11973 lasthit=j;
11974 lasthitclk=10;
11975 hitenemy=true;
11976 guys.spr(j)->lasthit=index;
11977 guys.spr(j)->lasthitclk=10;
11978 // guys.spr(j)->dir=guys.spr(j)->dir^1;
11979 }
11980 }
11981 }
11982
11983 if(!trapmove(dir) || clip() || hitenemy)
11984 {
11985 if(!trapmove(dir) || clip())
11986 {
11987 lasthit=-1;
11988 lasthitclk=0;
11989 }
11990
11991 if(get_bit(quest_rules,qr_MORESOUNDS))
11992 sfx(WAV_ZN1TAP,pan(int32_t(x)));
11993
11994 dir=dir^1;
11995 }
11996
11997 sprite::move(step);
11998 }
11999 else
12000 {
12001 if(!trapmove(dir) || clip())
12002 {
12003 if(get_bit(quest_rules,qr_MORESOUNDS))
12004 sfx(WAV_ZN1TAP,pan(int32_t(x)));
12005
12006 dir=dir^1;
12007 }
12008
12009 sprite::move(step);
12010 }
12011
12012 return enemy::animate(index);
12013 }
12014
12015 bool eTrap2::trapmove(int32_t ndir)
12016 {
12017 if(tmpscr->flags2&fFLOATTRAPS)
12018 return canmove(ndir,(zfix)1,spw_floater, 0, 0, 15, 15,false);
12019
12020 return canmove(ndir,(zfix)1,spw_water, 0, 0, 15, 15,false);
12021 }
12022
12023 bool eTrap2::clip()
12024 {
12025 switch(dir)
12026 {
12027 case up:
12028 if(y<=0) return true;
12029
12030 break;
12031
12032 case down:
12033 if(y>=160) return true;
12034
12035 break;
12036
12037 case left:
12038 if(x<=0) return true;
12039
12040 break;
12041
12042 case right:
12043 if(x>=240) return true;
12044
12045 break;
12046 }
12047
12048 return false;
12049 }
12050
12051 void eTrap2::draw(BITMAP *dest)
12052 {
12053 update_enemy_frame();
12054 enemy::draw(dest);
12055 }
12056
12057 int32_t eTrap2::takehit(weapon*)
12058 {
12059 return 0;
12060 }
12061
12062 eRock::eRock(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
12063 {
12064 //do not show "enemy appering" anim -DD
12065 clk=0;
12066 mainguy=false;
12067 clk2=-14;
12068 //Enemy Editor Size Tab
12069 if ( (d->SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12070 else hxofs = -2;
12071 if ( (d->SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12072 else hyofs = -2;
12073 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && d->hxsz >= 0 ) hxsz = d->hxsz;
12074 else hxsz = 20;
12075 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && d->hysz >= 0 ) hysz = d->hysz;
12076 else hysz=20;
12077
12078 if ( ((d->SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && d->txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12079 if ( ((d->SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && d->tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12080 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && d->hzsz >= 0 ) hzsz = d->hzsz;
12081 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
12082 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12083 {
12084 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12085 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12086 }
12087
12088 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
12089 //nets+1640;
12090 }
12091
12092 bool eRock::animate(int32_t index)
12093 {
12094 if(switch_hooked) return enemy::animate(index);
12095 if(fallclk||drownclk) return enemy::animate(index);
12096 if(dying)
12097 return Dead(index);
12098
12099 if(clk==0)
12100 {
12101 removearmos(x,y);
12102 }
12103
12104 if(++clk2==0) // start it
12105 {
12106 x=zc_oldrand()&0xF0;
12107 y=0;
12108 clk3=0;
12109 clk2=zc_oldrand()&15;
12110 }
12111
12112 if(clk2>16) // move it
12113 {
12114 if(clk3<=0) // start bounce
12115 {
12116 dir=zc_oldrand()&1;
12117
12118 if(x<32) dir=1;
12119
12120 if(x>208) dir=0;
12121 }
12122
12123 if(clk3<13+16)
12124 {
12125 x += dir ? 1 : -1; //right, left
12126 dummy_int[1]=dir;
12127
12128 if(clk3<2)
12129 {
12130 y-=2; //up
12131 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
12132 }
12133 else if(clk3<5)
12134 {
12135 y--; //up
12136 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
12137 }
12138 else if(clk3<8)
12139 {
12140 dummy_int[2]=(dummy_int[1]==1)?right:left;
12141 }
12142 else if(clk3<11)
12143 {
12144 y++; //down
12145 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
12146 }
12147 else
12148 {
12149 y+=2; //down
12150 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
12151 }
12152
12153 ++clk3;
12154 }
12155 else if(y<176)
12156 clk3=0; // next bounce
12157 else
12158 clk2 = -(zc_oldrand()&63); // back to top
12159 }
12160
12161 return enemy::animate(index);
12162 }
12163
12164 void eRock::drawshadow(BITMAP *dest, bool translucent)
12165 {
12166 if(clk2>=0)
12167 {
12168 int32_t tempy=yofs;
12169 flip = 0;
12170 int32_t fdiv = frate/4;
12171 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
12172 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
12173 efrate:((clk>=(frate>>1))?1:0);
12174 shadowtile = wpnsbuf[spr_shadow].tile+f2;
12175
12176 yofs+=8;
12177 yofs+=zc_max(0,zc_min(29-clk3,clk3));
12178 if(!shadow_overpit(this))
12179 enemy::drawshadow(dest, translucent);
12180 yofs=tempy;
12181 }
12182 }
12183
12184 void eRock::draw(BITMAP *dest)
12185 {
12186 if(clk2>=0 || fallclk||drownclk)
12187 {
12188 int32_t tempdir=dir;
12189 dir=dummy_int[2];
12190 update_enemy_frame();
12191 enemy::draw(dest);
12192 dir=tempdir;
12193 }
12194 }
12195
12196 int32_t eRock::takehit(weapon*)
12197 {
12198 return 0;
12199 }
12200
12201 eBoulder::eBoulder(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
12202 {
12203 clk=0;
12204 mainguy=false;
12205 clk2=-14;
12206 if ( (d->SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12207 else hxofs= -10;
12208 if ( (d->SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12209 else hyofs=-10;
12210 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && d->hxsz >= 0 ) hxsz = d->hxsz;
12211 else hxsz=36;
12212 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && d->hysz >= 0 ) hysz = d->hysz;
12213 else hysz=36;
12214 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && d->hzsz >= 0 ) hzsz = d->hzsz;
12215 else hzsz=16; //can't be jumped
12216
12217 if ( ((d->SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && d->txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12218 if ( ((d->SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && d->tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12219 if ( ((d->SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && d->hxsz >= 0 ) hxsz = d->hxsz;
12220 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
12221 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12222 {
12223 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12224 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12225 }
12226
12227 if ( (d->SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
12228 //nets+1680;
12229 }
12230
12231 bool eBoulder::animate(int32_t index)
12232 {
12233 if(switch_hooked) return enemy::animate(index);
12234 if(fallclk||drownclk) return enemy::animate(index);
12235 if(dying)
12236 return Dead(index);
12237
12238 if(clk==0)
12239 {
12240 removearmos(x,y);
12241 }
12242
12243 zfix *vert;
12244 vert = (moveflags & FLAG_USE_FAKE_Z) ? &fakez : get_bit(quest_rules,qr_ENEMIESZAXIS) ? &z : &y;
12245
12246 if(++clk2==0) // start it
12247 {
12248 x=zc_oldrand()&0xF0;
12249 y=-32;
12250 clk3=0;
12251 clk2=zc_oldrand()&15;
12252 }
12253
12254 if(clk2>16) // move it
12255 {
12256 if(clk3<=0) // start bounce
12257 {
12258 dir=zc_oldrand()&1;
12259
12260 if(x<32) dir=1;
12261
12262 if(x>208) dir=0;
12263 }
12264
12265 if(clk3<13+16)
12266 {
12267 x += dir ? 1 : -1; //right, left
12268 dummy_int[1]=dir;
12269
12270 if(clk3<2)
12271 {
12272 y-=2; //up
12273 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
12274 }
12275 else if(clk3<5)
12276 {
12277 y--; //up
12278 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
12279 }
12280 else if(clk3<8)
12281 {
12282 dummy_int[2]=(dummy_int[1]==1)?right:left;
12283 }
12284 else if(clk3<11)
12285 {
12286 y++; //down
12287 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
12288 }
12289 else
12290 {
12291 y+=2; //down
12292 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
12293 }
12294
12295 ++clk3;
12296 }
12297 else if(y<176)
12298 clk3=0; // next bounce
12299 else
12300 clk2 = -(zc_oldrand()&63); // back to top
12301 }
12302
12303 return enemy::animate(index);
12304 }
12305
12306 void eBoulder::drawshadow(BITMAP *dest, bool translucent)
12307 {
12308 if(clk2>=0)
12309 {
12310 int32_t tempy=yofs;
12311 flip = 0;
12312 int32_t f2=((clk<<2)/frate)<<1;
12313 shadowtile = wpnsbuf[spr_shadow].tile+f2;
12314 yofs+=zc_max(0,zc_min(29-clk3,clk3));
12315
12316 yofs+=8;
12317 xofs-=8;
12318 if(!shadow_overpit(this))
12319 enemy::drawshadow(dest, translucent);
12320 xofs+=16;
12321 ++shadowtile;
12322 if(!shadow_overpit(this))
12323 enemy::drawshadow(dest, translucent);
12324 yofs+=16;
12325 shadowtile+=20;
12326 if(!shadow_overpit(this))
12327 enemy::drawshadow(dest, translucent);
12328 xofs-=16;
12329 --shadowtile;
12330 if(!shadow_overpit(this))
12331 enemy::drawshadow(dest, translucent);
12332 xofs+=8;
12333 yofs=tempy;
12334 }
12335 }
12336
12337 void eBoulder::draw(BITMAP *dest)
12338 {
12339 if(clk2>=0 || fallclk||drownclk)
12340 {
12341 int32_t tempdir=dir;
12342 dir=dummy_int[2];
12343 update_enemy_frame();
12344 dir=tempdir;
12345 xofs-=8;
12346 yofs-=8;
12347 drawblock(dest,15);
12348 xofs+=8;
12349 yofs+=8;
12350 // enemy::draw(dest);
12351 }
12352 }
12353
12354 int32_t eBoulder::takehit(weapon*)
12355 {
12356 return 0;
12357 }
12358
12359 eProjectile::eProjectile(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk),
12360 minRange(get_bit(quest_rules, qr_BROKENSTATUES) ? 0 : Clk)
12361 {
12362 /* fixing
12363 hp=1;
12364 */
12365 mainguy=false;
12366 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
12367 hclk=clk; // the "no fire" range
12368 clk=0;
12369 clk3=96;
12370 timer=0;
12371 if(o_tile==0)
12372 {
12373 superman=1;
12374 hxofs=1000;
12375 }
12376 SIZEflags = d->SIZEflags;
12377 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12378 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
12379 // al_trace("Enemy txsz:%i\n", txsz);
12380 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12381 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
12382 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
12383 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
12384 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12385 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12386 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
12387 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
12388 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12389 {
12390 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12391 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12392 }
12393
12394 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
12395 }
12396
12397 bool eProjectile::animate(int32_t index)
12398 {
12399 if(switch_hooked) return enemy::animate(index);
12400 if(fallclk||drownclk) return enemy::animate(index);
12401 if(clk==0)
12402 {
12403 removearmos(x,y);
12404 }
12405
12406 double _MSVC2022_tmp1, _MSVC2022_tmp2;
12407 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
12408
12409 if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
12410 {
12411 dir=down;
12412 }
12413 else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
12414 {
12415 dir=right;
12416 }
12417 else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4)))
12418 {
12419 dir=up;
12420 }
12421 else
12422 {
12423 dir=left;
12424 }
12425
12426 if(!stunclk && ++clk3>80)
12427 {
12428 if(dmisc1==9) // Breath type
12429 {
12430 if(timer==0)
12431 {
12432 unsigned r=zc_oldrand();
12433
12434 if(!(r&63))
12435 {
12436 timer=zc_oldrand()%50+50;
12437 }
12438 }
12439
12440 if(timer>0)
12441 {
12442 if(timer%4==0)
12443 {
12444 FireBreath(false);
12445 }
12446
12447 if(--timer==0)
12448 {
12449 clk3=0;
12450 }
12451 }
12452 }
12453
12454 else // Not breath type
12455 {
12456 unsigned r=zc_oldrand();
12457
12458 if(!(r&63) && !HeroInRange(minRange))
12459 {
12460 FireWeapon();
12461
12462 if(get_bit(quest_rules, qr_BROKENSTATUES)==0 &&
12463 ((wpn==ewFireball || wpn==ewFireball2) || dmisc1==e1tNORMAL))
12464 {
12465 if(!((r>>7)&15))
12466 {
12467 x-=4;
12468 FireWeapon();
12469 x+=4;
12470 }
12471 }
12472
12473 clk3=0;
12474 }
12475 }
12476 }
12477
12478 return enemy::animate(index);
12479 }
12480
12481 void eProjectile::draw(BITMAP *dest)
12482 {
12483 update_enemy_frame();
12484 enemy::draw(dest);
12485 }
12486
12487 eTrigger::eTrigger(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
12488 {
12489 hxofs=1000;
12490 }
12491
12492 void eTrigger::draw(BITMAP *dest)
12493 {
12494 update_enemy_frame();
12495 enemy::draw(dest);
12496 }
12497
12498 void eTrigger::death_sfx()
12499 {
12500 //silent death
12501 }
12502
12503 eNPC::eNPC(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
12504 {
12505 o_tile+=wpnsbuf[iwNPCs].tile;
12506 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
12507 SIZEflags = d->SIZEflags;
12508 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12509 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
12510 // al_trace("Enemy txsz:%i\n", txsz);
12511 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12512 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
12513 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
12514 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
12515 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12516 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12517 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
12518 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
12519 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12520 {
12521 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12522 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12523 }
12524
12525 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
12526 }
12527
12528 bool eNPC::animate(int32_t index)
12529 {
12530 if(switch_hooked) return enemy::animate(index);
12531 if(dying)
12532 return Dead(index);
12533
12534 if(clk==0)
12535 {
12536 removearmos(x,y);
12537 }
12538
12539 switch(dmisc2)
12540 {
12541 case 0:
12542 {
12543 double _MSVC2022_tmp1, _MSVC2022_tmp2;
12544 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
12545
12546 if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
12547 {
12548 dir=down;
12549 }
12550
12551 else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
12552 {
12553 dir=right;
12554 }
12555 else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/8)))
12556 {
12557 dir=up;
12558 }
12559 else
12560 {
12561 dir=left;
12562 }
12563 }
12564 break;
12565
12566 case 1:
12567 halting_walk(rate, homing, 0, hrate, 48);
12568
12569 if(clk2==1 && (misc < dmisc1) && !(zc_oldrand()&15))
12570 {
12571 newdir(rate, homing, 0);
12572 clk2=48;
12573 ++misc;
12574 }
12575
12576 if(clk2==0)
12577 misc=0;
12578
12579 break;
12580 }
12581
12582 return enemy::animate(index);
12583 }
12584
12585 void eNPC::draw(BITMAP *dest)
12586 {
12587 update_enemy_frame();
12588 enemy::draw(dest);
12589 }
12590
12591 int32_t eNPC::takehit(weapon*)
12592 {
12593 return 0;
12594 }
12595
12596 eSpinTile::eSpinTile(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
12597 {
12598 if(clk>0) // clk>0 when created by a Spinning Tile combo
12599 {
12600 o_tile=clk;
12601 cs=id>>12;
12602 }
12603
12604 id=id&0xFFF;
12605 clk=0;
12606 step=0;
12607 mainguy=false;
12608 SIZEflags = d->SIZEflags;
12609 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12610 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
12611 // al_trace("Enemy txsz:%i\n", txsz);
12612 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12613 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
12614 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
12615 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
12616 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12617 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12618 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
12619 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
12620 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12621 {
12622 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12623 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12624 }
12625
12626 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
12627 }
12628
12629 void eSpinTile::facehero()
12630 {
12631 if(Hero.x-x==0)
12632 {
12633 if (Hero.y + 8 < y)
12634 dir = up;
12635 else
12636 dir = down;
12637 }
12638 else
12639 {
12640 double _MSVC2022_tmp1, _MSVC2022_tmp2;
12641 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
12642
12643 if((ddir <= -5.0*PI/8.0) && (ddir > -7.0*PI/8.0))
12644 {
12645 dir=l_down;
12646 }
12647 else if ((ddir <= -3.0*PI / 8.0) && (ddir > -5.0*PI / 8.0))
12648 {
12649 dir=down;
12650 }
12651 else if ((ddir <= -1.0*PI / 8.0) && (ddir > -3.0*PI / 8.0))
12652 {
12653 dir=r_down;
12654 }
12655 else if ((ddir <= 1.0*PI / 8.0) && (ddir > -1.0*PI / 8.0))
12656 {
12657 dir=right;
12658 }
12659 else if ((ddir <= 3.0*PI / 8.0) && (ddir > 1.0*PI / 8.0))
12660 {
12661 dir=r_up;
12662 }
12663 else if ((ddir <= 5.0*PI / 8.0) && (ddir > 3.0*PI / 8.0))
12664 {
12665 dir=up;
12666 }
12667 else if ((ddir <= 7.0*PI / 8.0) && (ddir > 5.0*PI / 8.0))
12668 {
12669 dir=l_up;
12670 }
12671 else
12672 {
12673 dir=left;
12674 }
12675 }
12676 }
12677
12678
12679 bool eSpinTile::animate(int32_t index)
12680 {
12681 if(switch_hooked) return enemy::animate(index);
12682 if(fallclk||drownclk) return enemy::animate(index);
12683 if(dying)
12684 {
12685 return Dead(index);
12686 }
12687
12688 if(clk==0)
12689 {
12690 removearmos(x,y);
12691 }
12692
12693 ++misc;
12694
12695 if(misc==96)
12696 {
12697 facehero();
12698 double _MSVC2022_tmp1, _MSVC2022_tmp2;
12699 double ddir=atan2_MSVC2022_FIX(double((Hero.y)-y),double(Hero.x-x));
12700 angular=true;
12701 angle=ddir;
12702 step=zslongToFix(dstep*100);
12703 }
12704
12705 if(y>186 || y<=-16 || x>272 || x<=-16)
12706 kickbucket();
12707
12708 sprite::move(step);
12709 return enemy::animate(index);
12710 }
12711
12712 void eSpinTile::draw(BITMAP *dest)
12713 {
12714 update_enemy_frame();
12715 y-=(misc>>4);
12716 yofs+=2;
12717 enemy::draw(dest);
12718 yofs-=2;
12719 y+=(misc>>4);
12720 }
12721
12722 void eSpinTile::drawshadow(BITMAP *dest, bool translucent)
12723 {
12724 flip = 0;
12725 shadowtile = wpnsbuf[spr_shadow].tile+(clk%4);
12726 yofs+=4;
12727 if(!shadow_overpit(this))
12728 enemy::drawshadow(dest, translucent);
12729 yofs-=4;
12730 }
12731
12732 eZora::eZora(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,0)
12733 {
12734 //these are here to bypass compiler warnings about unused arguments
12735 Clk=Clk;
12736 mainguy=false;
12737 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
12738 /*if((x>-17 && x<0) && iswaterex(tmpscr->data[(((int32_t)y&0xF0)+((int32_t)x>>4))]))
12739 {
12740 clk=1;
12741 }*/
12742 //nets+880;
12743 SIZEflags = d->SIZEflags;
12744 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12745 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
12746 // al_trace("Enemy txsz:%i\n", txsz);
12747 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12748 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
12749 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
12750 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
12751 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12752 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12753 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
12754 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
12755 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12756 {
12757 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12758 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12759 }
12760
12761 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
12762 }
12763
12764 void eZora::facehero()
12765 {
12766 if(Hero.x-x==0)
12767 {
12768 dir=(Hero.y+8<y)?up:down;
12769 }
12770 else
12771 {
12772 double _MSVC2022_tmp1, _MSVC2022_tmp2;
12773 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
12774
12775 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
12776 {
12777 dir=l_down;
12778 }
12779 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
12780 {
12781 dir=down;
12782 }
12783 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
12784 {
12785 dir=r_down;
12786 }
12787 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
12788 {
12789 dir=right;
12790 }
12791 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
12792 {
12793 dir=r_up;
12794 }
12795 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
12796 {
12797 dir=up;
12798 }
12799 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
12800 {
12801 dir=l_up;
12802 }
12803 else
12804 {
12805 dir=left;
12806 }
12807 }
12808 }
12809
12810 bool eZora::animate(int32_t index)
12811 {
12812 if(switch_hooked) return enemy::animate(index);
12813 if(dying)
12814 return Dead(index);
12815
12816 if(clk==0)
12817 {
12818 removearmos(x,y);
12819 }
12820
12821 if(watch)
12822 {
12823 ++clock_zoras[id];
12824 return true;
12825 }
12826
12827 if(get_bit(quest_rules,qr_NEWENEMYTILES))
12828 {
12829 facehero();
12830 }
12831
12832 switch(clk)
12833 {
12834 case 0: // reposition him
12835 {
12836 int32_t t=0;
12837 int32_t pos2=zc_oldrand()%160 + 16;
12838 bool placed=false;
12839
12840 while(!placed && t<160)
12841 {
12842 int32_t watertype = iswaterex(tmpscr->data[pos2], currmap, currscr, -1, ((pos2)%16*16), ((pos2)&0xF0), false, true, true, (bool)(editorflags & ENEMY_FLAG7));
12843 if(watertype && ((editorflags & ENEMY_FLAG6) ||
12844 ((combobuf[watertype].usrflags&cflag1) && (editorflags & ENEMY_FLAG5))
12845 || (!(combobuf[watertype].usrflags&cflag1) && !(editorflags & ENEMY_FLAG5))) && (pos2&15)>0 && (pos2&15)<15)
12846 {
12847 x=(pos2&15)<<4;
12848 y=pos2&0xF0;
12849 if (!(editorflags & ENEMY_FLAG8)) hp=guysbuf[id&0xFFF].hp; // refill life each time, unless the flag is checked.
12850 hxofs=1000; // avoid hit detection
12851 stunclk=0;
12852 placed=true;
12853 }
12854
12855 pos2+=19;
12856
12857 if(pos2>=176)
12858 pos2-=160;
12859
12860 ++t;
12861 }
12862
12863 if(!placed || whistleclk>=88) // can't place him, he's gone
12864 return true;
12865
12866 }
12867 break;
12868
12869 case 35:
12870 if(!get_bit(quest_rules,qr_NEWENEMYTILES))
12871 {
12872 dir=(Hero.y+8<y)?up:down;
12873 }
12874
12875 hxofs=0;
12876 break;
12877
12878 case 35+19:
12879 addEwpn(x,y,z,wpn,2,wdp,dir,getUID(), 0, fakez);
12880 sfx(wpnsfx(wpn),pan(int32_t(x)));
12881 break;
12882
12883 case 35+66:
12884 hxofs=1000;
12885 break;
12886
12887 case 198:
12888 clk=-1;
12889 break;
12890 }
12891
12892 return enemy::animate(index);
12893 }
12894
12895 void eZora::draw(BITMAP *dest)
12896 {
12897 if(clk<3)
12898 return;
12899
12900 update_enemy_frame();
12901 enemy::draw(dest);
12902 }
12903
12904 bool eZora::isSubmerged() const
12905 {
12906 return ( clk < 3 );
12907 }
12908
12909
4/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
32 eStalfos::eStalfos(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
12910 24 {
12911 8 multishot= timer = fired = dashing = 0;
12912 8 hashero = false;
12913 8 dummy_bool[0]=false;
12914 8 shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
12915
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if(dmisc9==e9tARMOS && zc_oldrand()&1)
12916 {
12917 step=zslongToFix(dmisc10*100);
12918
12919 if(anim==aARMOS4) o_tile+=20;
12920 }
12921
12922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if(flags & guy_fadeflicker)
12923 {
12924 clk=0;
12925 superman = 1;
12926 fading=fade_flicker;
12927 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
12928 dir=down;
12929
12930 if(!canmove(down,(zfix)8,spw_none,false))
12931 clk3=int32_t(13.0/step);
12932 }
12933
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if(flags & guy_fadeinstant)
12934 {
12935 clk=0;
12936 }
12937
12938
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 shadowdistance = 0;
12939 8 clk4 = clk5 = 0;
12940 //nets+2380;
12941 8 SIZEflags = d->SIZEflags;
12942
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
12943 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
12944 // al_trace("Enemy txsz:%i\n", txsz);
12945
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
12946
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
12947
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
12948
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
12949
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
12950
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
12951 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
12952
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
12953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
12954 {
12955 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
12956 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
12957 }
12958
12959
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
12960 16 }
12961
12962 1360 bool eStalfos::animate(int32_t index)
12963 {
12964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1360 times.
1360 if(switch_hooked) return enemy::animate(index);
12965
2/4
✓ Branch 0 taken 1360 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1360 times.
1360 if(fallclk||drownclk)
12966 {
12967 return enemy::animate(index);
12968 }
12969
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1288 times.
1360 if(dying)
12970 {
12971
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if(hashero)
12972 {
12973 Hero.setEaten(0);
12974 hashero=false;
12975 }
12976
12977
1/14
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
72 if(dmisc9==e9tROPE && dmisc2==e2tBOMBCHU && !fired && (hp<=0 && !immortal) && hp>-1000 && wpn>wEnemyWeapons)
12978 {
12979 hp=-1000;
12980 weapon *ew=new weapon(x,y,z, wpn, 0, dmisc4, dir,-1,getUID(),false);
12981 Ewpns.add(ew);
12982 ew->fakez = fakez;
12983
12984 if(wpn==ewSBomb || wpn==ewBomb)
12985 {
12986 ew->step=0;
12987 ew->id=wpn;
12988 ew->misc=50;
12989 ew->clk=48;
12990 }
12991
12992 fired=true;
12993 }
12994
3/6
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
72 else if(wpn && wpn!=ewBrang && dmisc2==e2tFIREOCTO) // Fire Octo
12995 {
12996 if(!dummy_bool[0])
12997 {
12998 int32_t wpn2 = wpn+dmisc3;
12999
13000 if(wpn2 <= wEnemyWeapons || wpn2 >= wMax)
13001 {
13002 wpn2=wpn;
13003 }
13004
13005 dummy_bool[0]=true;
13006 addEwpn(x,y,z,wpn2,0,dmisc4,up, getUID(), 0, fakez);
13007 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13008 addEwpn(x,y,z,wpn2,0,dmisc4,down, getUID(), 0, fakez);
13009 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13010 addEwpn(x,y,z,wpn2,0,dmisc4,left, getUID(), 0, fakez);
13011 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13012 addEwpn(x,y,z,wpn2,0,dmisc4,right, getUID(), 0, fakez);
13013 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13014 addEwpn(x,y,z,wpn2,0,dmisc4,l_up, getUID(), 0, fakez);
13015 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13016 addEwpn(x,y,z,wpn2,0,dmisc4,r_up, getUID(), 0, fakez);
13017 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13018 addEwpn(x,y,z,wpn2,0,dmisc4,l_down, getUID(), 0, fakez);
13019 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13020 addEwpn(x,y,z,wpn2,0,dmisc4,r_down, getUID(), 0, fakez);
13021 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
13022 sfx(wpnsfx(wpn2),pan(int32_t(x)));
13023 }
13024 }
13025
13026 72 KillWeapon();
13027 72 return Dead(index);
13028 }
13029 //vire split
13030 //2.10 checked !fslide(), but nothing uses that now anyway. -Z
13031 //Perhaps the problem occurs when vires die because they have < 0 HP, in this check?
13032
5/14
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1284 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1288 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
1288 else if(((hp<=0 && !immortal) && dmisc2==e2tSPLIT) || (dmisc2==e2tSPLITHIT && hp>0 && hp<guysbuf[id&0xFFF].hp && !slide() && (sclk&255)<=1)) //Split into enemies
13033 {
13034 stop_bgsfx(index);
13035 int32_t kids = guys.Count();
13036 int32_t id2=dmisc3;
13037 for(int32_t i=0; i < dmisc4; i++)
13038 {
13039 // if (addenemy(x,y,id2+(guysbuf[id2].family==eeKEESE ? 0 : ((i+1)<<12)),-21-(i%4)))
13040 if(addenemy(x,y,id2+(guysbuf[id2].family==eeKEESE ? 0 : ((editorflags & ENEMY_FLAG5) ? 0 : (i<<12))),-21-(i%4)))
13041 ((enemy*)guys.spr(kids+i))->count_enemy = false;
13042 }
13043
13044 if(itemguy) // Hand down the carried item
13045 {
13046 guycarryingitem = guys.Count()-1;
13047 ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
13048 itemguy = false;
13049 }
13050
13051 if(hashero)
13052 {
13053 Hero.setEaten(0);
13054 hashero=false;
13055 }
13056
13057 if(deadsfx > 0 && dmisc2==e2tSPLIT)
13058 sfx(deadsfx,pan(int32_t(x)));
13059
13060 return true;
13061 }
13062 /*
13063 else if((dmisc2==e2tSPLITHIT && (hp<=0 && !immortal) &&!slide())) //Possible vires fix; or could cause goodness knows what. -Z
13064 {
13065 stop_bgsfx(index);
13066 int32_t kids = guys.Count();
13067 int32_t id2=dmisc3;
13068
13069 for(int32_t i=0; i < dmisc4; i++)
13070 {
13071 // if (addenemy(x,y,id2+(guysbuf[id2].family==eeKEESE ? 0 : ((i+1)<<12)),-21-(i%4)))
13072 if(addenemy(x,y,id2+(guysbuf[id2].family==eeKEESE ? 0 : (i<<12)),-21-(i%4)))
13073 ((enemy*)guys.spr(kids+i))->count_enemy = false;
13074 }
13075
13076 if(itemguy) // Hand down the carried item
13077 {
13078 guycarryingitem = guys.Count()-1;
13079 ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
13080 itemguy = false;
13081 }
13082
13083 if(hashero)
13084 {
13085 Hero.setEaten(0);
13086 hashero=false;
13087 }
13088
13089 return true;
13090 }
13091 */
13092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
1288 if(fading)
13093 {
13094 if(++clk4 > 60)
13095 {
13096 clk4=0;
13097 superman=0;
13098 fading=0;
13099
13100 if(flags2&cmbflag_armos && z==0 && fakez == 0)
13101 {
13102 //if a custom size (not 16px by 16px)
13103
13104 //if a custom size (not 16px by 16px)
13105 if (txsz > 1 || tysz > 1 || (SIZEflags&guyflagOVERRIDE_HIT_WIDTH) || (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) )//remove more than one combo based on enemy size
13106 {
13107 //zprint("spawn big enemy from armos\n");
13108 //if removing a block, then adjust y by -1 as the enemy spawns at y+1
13109 for(int32_t dx = 0; dx < tysz; dx ++)
13110 {
13111 for(int32_t dy = 0; dy < tysz; dy++)
13112 {
13113 removearmos((int32_t)x+(dx*16),(int32_t)y+(dy*16)+1);
13114 did_armos = false;
13115 }
13116 removearmos((int32_t)x+(dx*16), (int32_t)y+((tysz-1)*16)+1);
13117 did_armos = false;
13118 }
13119 for(int32_t dy = 0; dy < tysz; dy ++)
13120 {
13121 removearmos((int32_t)x+((txsz-1)*16), (int32_t)y+(dy*16)+1);
13122 did_armos = false;
13123 }
13124 removearmos((int32_t)x+((txsz-1)*16), (int32_t)y+((tysz-1)*16)+1);
13125 }
13126 else removearmos(x,y);
13127 /*
13128 if (txsz > 1 || tysz > 1 || (SIZEflags&guyflagOVERRIDE_HIT_WIDTH) || (SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) )//remove more than one combo based on enemy size
13129 {
13130 //if removing a block, then adjust y by -1 as the enemy spawns at y+1
13131 for(int32_t dx = 0; dx < hxsz; dx += 16)
13132 {
13133 for(int32_t dy = 0; dy < hysz; dy += 16)
13134 {
13135 removearmos((int32_t)x+dx+hxofs,(int32_t)y+dy+hyofs+1);
13136 did_armos = false;
13137 }
13138 removearmos((int32_t)x+dx+hxofs, (int32_t)y+hyofs+(hysz-1)-1);
13139 did_armos = false;
13140 }
13141 for(int32_t dy = 0; dy < hysz; dy += 16)
13142 {
13143 removearmos((int32_t)x+hxofs+(hxsz-1), (int32_t)y+dy+hyofs-1);
13144 did_armos = false;
13145 }
13146 removearmos((int32_t)x+hxofs+(hxsz-1), (int32_t)y+hyofs+(hysz-1)-1);
13147 }
13148 else removearmos(x,y);
13149 */
13150
13151 }
13152
13153 clk2=0;
13154
13155 newdir();
13156 }
13157 else return enemy::animate(index);
13158 }
13159
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1288 else if(flags2&cmbflag_armos && z==0 && fakez == 0 && clk==0)
13160 removearmos(x,y);
13161
13162
13163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
1288 if(hashero)
13164 {
13165 Hero.setX(x);
13166 Hero.setY(y);
13167 ++clk2;
13168
13169 if(clk2==(dmisc8==0 ? 95 : dmisc8))
13170 {
13171 switch(dmisc7)
13172 {
13173 case e7tEATITEMS:
13174 {
13175 for(int32_t i=0; i<MAXITEMS; i++)
13176 {
13177 if(itemsbuf[i].flags&ITEM_EDIBLE)
13178 game->set_item(i, false);
13179 }
13180
13181 break;
13182 }
13183
13184 case e7tEATMAGIC:
13185 game->change_dmagic(-1*game->get_magicdrainrate());
13186 break;
13187
13188 case e7tEATRUPEES:
13189 game->change_drupy(-1);
13190 break;
13191 }
13192
13193 clk2=0;
13194 }
13195
13196 if((clk&0x18)==8) // stop its animation on the middle frame
13197 --clk;
13198 }
13199
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1288 else if(!(wpn==ewBrang && WeaponOut())) //WeaponOut uses misc
13200 {
13201 // Movement engine
13202
3/6
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 1138 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1138 times.
✗ Branch 5 not taken.
1288 if(clk>=0) switch(id>>12)
13203 {
13204 case 0: // Normal movement
13205
13206 /*
13207 if((dmisc9==e9tLEEVER || dmisc9==e9tZ3LEEVER) && !slide()) //Leever
13208 {
13209 // Overloading clk4 (Tribble clock) here...
13210 step=17/100.0;
13211 if(clk4<32) misc=1;
13212 else if(clk4<48) misc=2;
13213 else if(clk4<300) { misc=3; step = dstep/100.0; }
13214 else if(clk4<316) misc=2;
13215 else if(clk4<412) misc=1;
13216 else if(clk4<540) { misc=0; step=0; }
13217 else clk4=0;
13218 if(clk4==48) clk=0;
13219 hxofs=(misc>=2)?0:1000;
13220 if (dmisc9==e9tLEEVER)
13221 variable_walk(rate, homing, 0);
13222 else
13223 variable_walk_8(rate, homing, 4, 0);
13224 break;
13225 }
13226 */
13227
2/4
✓ Branch 0 taken 1138 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1138 times.
1138 if(dmisc9==e9tVIRE || dmisc9==e9tPOLSVOICE) //Vire
13228 {
13229 vire_hop();
13230 break;
13231 }
13232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1138 times.
1138 else if(dmisc9==e9tROPE) //Rope charge
13233 {
13234 if(!fired && dashing && !stunclk && !watch && !frozenclock)
13235 {
13236 if(dmisc2==e2tBOMBCHU && HeroInRange(16) && wpn+dmisc3 > wEnemyWeapons) //Bombchu
13237 {
13238
13239 if ( get_bit(quest_rules,qr_BOMBCHUSUPERBOMB) )
13240 {
13241 hp=-1000;
13242
13243 if(wpn+dmisc3 > wEnemyWeapons && wpn+dmisc3 < wMax)
13244 {
13245 weapon *ew=new weapon(x,y,z, wpn+dmisc3, 0, dmisc4, dir,-1,getUID());
13246 Ewpns.add(ew);
13247 ew->fakez = fakez;
13248
13249 if(wpn==ewSBomb || wpn==ewBomb)
13250 {
13251 ew->step=0;
13252 ew->id=wpn+dmisc3;
13253 ew->misc=50;
13254 ew->clk=48;
13255 }
13256
13257 fired=true;
13258 }
13259 else
13260 {
13261 weapon *ew=new weapon(x,y,z, wpn, 0, dmisc4, dir,-1,getUID());
13262 Ewpns.add(ew);
13263 ew->fakez = fakez;
13264
13265 if(wpn==ewSBomb || wpn==ewBomb)
13266 {
13267 ew->step=0;
13268 ew->id=wpn;
13269 ew->misc=50;
13270 ew->clk=48;
13271 }
13272
13273 fired=true;
13274 }
13275 }
13276
13277 else
13278 {
13279 hp=-1000;
13280
13281 int32_t wpn2;
13282 if(wpn+dmisc3 > wEnemyWeapons && wpn+dmisc3 < wMax)
13283 wpn2=wpn;
13284 else
13285 wpn2=wpn;
13286
13287 weapon *ew=new weapon(x,y,z, wpn2, 0, dmisc4, dir,-1,getUID());
13288 Ewpns.add(ew);
13289 ew->fakez = fakez;
13290
13291 if(wpn2==ewSBomb || wpn2==ewBomb)
13292 {
13293 ew->step=0;
13294 ew->id=wpn2;
13295 ew->misc=50;
13296 ew->clk=48;
13297 }
13298
13299 fired=true;
13300 }
13301 }
13302 }
13303
13304 charge_attack();
13305 break;
13306 }
13307 /*
13308 * Boomerang-throwers have a halt count of 1
13309 * Zols have a halt count of (zc_oldrand()&7)<<4
13310 * Gels have a halt count of ((zc_oldrand()&7)<<3)+2
13311 * Everything else has 48
13312 */
13313 else
13314 {
13315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1138 times.
1138 if(wpn==ewBrang) // Goriya
13316 {
13317 halting_walk(rate,homing,0,hrate, 1);
13318 }
13319
2/4
✓ Branch 0 taken 1138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1138 times.
✗ Branch 3 not taken.
1138 else if(dmisc9==e9tNORMAL && wpn==0)
13320 {
13321 if(dmisc2==e2tSPLITHIT) // Zol
13322 {
13323 halting_walk(rate,homing,0,hrate,(zc_oldrand()&7)<<4);
13324 }
13325 else if(frate<=8 && starting_hp==1) // Gel
13326 {
13327 halting_walk(rate,homing,0,hrate,((zc_oldrand()&7)<<3)+2);
13328 }
13329 else // Other
13330 {
13331 halting_walk(rate,homing,0,hrate, 48);
13332 }
13333 }
13334 else // Other
13335 {
13336 1138 halting_walk(rate,homing,0,hrate, 48);
13337 }
13338 }
13339
13340 //if not in midair, and Hero's swinging sword is nearby, jump.
13341 /*if (dmisc9==e9tZ3STALFOS && z==0 && (!(isSideViewGravity()) || !_walkflag(x,y+16,0))
13342 && Hero.getAttackClk()==5 && Hero.getAttack()==wSword && distance(x,y,Hero.getX(),Hero.getY())<32)
13343 {
13344 facehero(false);
13345 sclk=16+((dir^1)<<8);
13346 fall=-FEATHERJUMP;
13347 sfx(WAV_ZN1JUMP,pan(int32_t(x)));
13348 }*/
13349 1138 break;
13350
13351 // Following cases are for just after creation-by-splitting.
13352 case 1:
13353 if(misc==1)
13354 {
13355 dir=up;
13356 step=8;
13357 }
13358
13359 if(misc<=2)
13360 {
13361 move(step);
13362
13363 if(!canmove(dir,(zfix)0,0,false))
13364 dir=down;
13365 }
13366
13367 if(misc==3)
13368 {
13369 if(canmove(right,(zfix)16,0,false))
13370 x+=16;
13371 }
13372
13373 ++misc;
13374 break;
13375
13376 case 2:
13377 if(misc==1)
13378 {
13379 dir=down;
13380 step=8;
13381 }
13382
13383 if(misc<=2)
13384 {
13385 move(step);
13386 /*
13387 if(!canmove(dir,(zfix)0,0,false))
13388 dir=up;
13389 */
13390 }
13391
13392 if(misc==3)
13393 {
13394 if(canmove(left,(zfix)16,0,false))
13395 x-=16;
13396 }
13397
13398 ++misc;
13399 break;
13400
13401 default:
13402 if(misc==1)
13403 {
13404 dir=(zc_oldrand()%4);
13405 step=8;
13406 }
13407
13408 if(misc<=2)
13409 {
13410 move(step);
13411
13412 if(!canmove(dir,(zfix)0,0,false))
13413 dir=dir^1;
13414 }
13415
13416 if(misc==3)
13417 {
13418 if(dir >= left && canmove(dir,(zfix)16,0,false))
13419 x+=(dir==left ? -16 : 16);
13420 }
13421
13422 ++misc;
13423 break;
13424 1138 }
13425
13426
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1288 if(id>>12 && misc>=4) //recently spawned by a split enemy
13427 {
13428 id&=0xFFF;
13429 step = zslongToFix(dstep*100);
13430
13431 if(x<32) x=32;
13432
13433 if(x>208) x=208;
13434
13435 if(y<32) y=32;
13436
13437 if(y>128) y=128;
13438
13439 misc=3;
13440 }
13441 1288 }
13442 else
13443 {
13444 //sfx(wpnsfx(wpn),pan(int32_t(x)));
13445 if(clk2>2) clk2--;
13446 }
13447
13448 // Fire Zol
13449
2/8
✓ Branch 0 taken 1288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1288 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1288 if(wpn && dmisc1==e1tEACHTILE && clk2==1 && !hclk)
13450 {
13451 addEwpn(x,y,z,wpn,0,wdp,dir, getUID(), 0, fakez);
13452 sfx(wpnsfx(wpn),pan(int32_t(x)));
13453
13454 int32_t i=Ewpns.Count()-1;
13455 weapon *ew = (weapon*)(Ewpns.spr(i));
13456
13457 if(wpn==ewFIRETRAIL && wpnsbuf[ewFIRETRAIL].frames>1)
13458 {
13459 ew->aframe=zc_oldrand()%wpnsbuf[ewFIRETRAIL].frames;
13460 if ( ew->do_animation ) ew->tile+=ew->aframe;
13461 }
13462 }
13463 // Goriya
13464
1/16
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1288 else if(wpn==ewBrang && clk2==1 && sclk==0 && !stunclk && !frozenclock && !watch && wpn && !WeaponOut())
13465 {
13466 misc=index+100;
13467 Ewpns.add(new weapon(x,y-fakez,z,wpn,misc,wdp,dir, -1,getUID(),false));
13468 ((weapon*)Ewpns.spr(Ewpns.Count()-1))->dummy_bool[0]=false;
13469
13470 if(dmisc1==2)
13471 {
13472 int32_t ndir=dir;
13473
13474 if(Hero.x-x==0)
13475 {
13476 ndir=(Hero.y+8<y)?up:down;
13477 }
13478 else //turn to face Hero
13479 {
13480 double _MSVC2022_tmp1, _MSVC2022_tmp2;
13481 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
13482
13483 if((ddir<=(((-2)*PI)/8))&&(ddir>(((-6)*PI)/8)))
13484 {
13485 ndir=down;
13486 }
13487 else if((ddir<=(((2)*PI)/8))&&(ddir>(((-2)*PI)/8)))
13488 {
13489 ndir=right;
13490 }
13491 else if((ddir<=(((6)*PI)/8))&&(ddir>(((2)*PI)/8)))
13492 {
13493 ndir=up;
13494 }
13495 else
13496 {
13497 ndir=left;
13498 }
13499 }
13500
13501 ((weapon*)Ewpns.spr(Ewpns.Count()-1))->dummy_bool[0]=true;
13502
13503 if(canmove(ndir,false))
13504 {
13505 dir=ndir;
13506 }
13507 }
13508 }
13509
10/16
✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1280 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
1288 else if((clk2==16 || dmisc1==e1tCONSTANT) && dmisc1!=e1tEACHTILE && wpn && wpn!=ewBrang && sclk==0 && !stunclk && !frozenclock && !watch)
13510
1/3
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
8 switch(dmisc1)
13511 {
13512 case e1tCONSTANT: //Deathnut
13513 {
13514 // Overloading clk5 (Like Like clock) to avoid making another clock just for this attack...
13515 if(clk5>64)
13516 {
13517 clk5=0;
13518 fired=false;
13519 }
13520
13521 clk5+=(zc_oldrand()&3);
13522
13523 if((clk5>24)&&(clk5<52))
13524 {
13525 if ( do_animation )tile+=20; //firing
13526
13527 if(!fired&&(clk5>=38))
13528 {
13529 Ewpns.add(new weapon(x,y,z, wpn, 0, wdp, dir, -1,getUID(),false));
13530 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
13531 sfx(wpnsfx(wpn),pan(int32_t(x)));
13532 fired=true;
13533 }
13534 }
13535
13536 break;
13537 }
13538
13539 case e1tFIREOCTO: //Fire Octo
13540 timer=zc_oldrand()%50+50;
13541 break;
13542
13543 default:
13544 8 FireWeapon();
13545 8 break;
13546 8 }
13547
13548 /* Fire again if:
13549 * - clk2 about to run out
13550 * - not already double-firing (dmisc1 is 1)
13551 * - not carrying Hero
13552 * - one in 0xF chance
13553 */
13554
3/10
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1280 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1288 if(clk2==1 && (multishot < dmisc6) && dmisc1 != e1tEACHTILE && !hashero && !(zc_oldrand()&15))
13555 {
13556 #if 1
13557 newdir(rate, homing, grumble);
13558 #else
13559 dir^=2;
13560 #endif
13561 clk2=28;
13562 ++multishot;
13563 }
13564
13565
2/2
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 869 times.
1288 if(clk2==0)
13566 {
13567 869 multishot = 0;
13568 869 }
13569
13570
1/2
✓ Branch 0 taken 1288 times.
✗ Branch 1 not taken.
1288 if(timer) //Fire Octo
13571 {
13572 clk2=15; //this keeps the octo in place until he's done firing
13573
13574 if(!(timer%4))
13575 {
13576 FireBreath(false);
13577 }
13578
13579 --timer;
13580 }
13581
13582
1/2
✓ Branch 0 taken 1288 times.
✗ Branch 1 not taken.
1288 if(dmisc2==e2tTRIBBLE)
13583 ++clk4;
13584
13585
2/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1288 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1288 if(clk4==(dmisc5 ? dmisc5 : 256) && (dmisc2==e2tTRIBBLE) && dmisc3 && dmisc4)
13586 {
13587 int32_t kids = guys.Count();
13588 int32_t id2=dmisc3;
13589
13590 for(int32_t i=0; i<dmisc4; i++)
13591 {
13592 if(addenemy(x,y,id2,-24))
13593 {
13594 if(itemguy) // Hand down the carried item
13595 {
13596 guycarryingitem = guys.Count()-1;
13597 ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
13598 itemguy = false;
13599 }
13600
13601 ((enemy*)guys.spr(kids+i))->count_enemy = false;
13602 }
13603 }
13604
13605 if(hashero)
13606 {
13607 Hero.setEaten(0);
13608 hashero=false;
13609 }
13610
13611 stop_bgsfx(index);
13612 return true;
13613 }
13614
13615 1288 return enemy::animate(index);
13616 1360 }
13617
13618 1364 void eStalfos::draw(BITMAP *dest)
13619 {
13620 /*if ((dmisc9==e9tLEEVER || dmisc9==e9tZ3LEEVER) && misc<=0) //Submerged
13621 {
13622 clk4--; //Kludge
13623 return;
13624 }*/
13625
13626 /*if ((dmisc9==e9tLEEVER || dmisc9==e9tZ3LEEVER) && misc>1)
13627 {
13628 cs = dcset;
13629 }*/
13630 1364 update_enemy_frame();
13631
13632
3/8
✓ Branch 0 taken 1364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1364 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1364 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1364 if(!fallclk&&!drownclk&&(dmisc2==e2tBOMBCHU)&&dashing)
13633 {
13634 if ( do_animation )tile+=20;
13635 }
13636
13637 1364 enemy::draw(dest);
13638 1364 }
13639
13640 void eStalfos::drawshadow(BITMAP *dest, bool translucent)
13641 {
13642 int32_t tempy=yofs;
13643
13644 /*
13645 if (clk6 && dir>=left && !get_bit(quest_rules,qr_ENEMIESZAXIS)) {
13646 flip = 0;
13647 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
13648 (clk/(frate/4)):((clk>=(frate>>1))?1:0);
13649 shadowtile = wpnsbuf[spr_shadow].tile+f2;
13650 yofs+=(((int32_t)y+17)&0xF0)-y;
13651 yofs+=8;
13652 }
13653 */
13654 if((dmisc9 == e9tPOLSVOICE || dmisc9==e9tVIRE) && !get_bit(quest_rules,qr_ENEMIESZAXIS))
13655 {
13656 flip = 0;
13657 int32_t fdiv = frate/4;
13658 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
13659
13660 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
13661 efrate:((clk>=(frate>>1))?1:0);
13662 shadowtile = wpnsbuf[spr_shadow].tile;
13663
13664 if(get_bit(quest_rules,qr_NEWENEMYTILES))
13665 {
13666 shadowtile+=f2;
13667 }
13668 else
13669 {
13670 shadowtile+=f2?1:0;
13671 }
13672
13673 yofs+=shadowdistance;
13674 yofs+=8;
13675 }
13676 if((dmisc9 == e9tPOLSVOICE || dmisc9==e9tVIRE) && !get_bit(quest_rules,qr_POLVIRE_NO_SHADOW))
13677 {
13678 flip = 0;
13679 int32_t fdiv = frate/4;
13680 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
13681
13682 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
13683 efrate:((clk>=(frate>>1))?1:0);
13684 shadowtile = wpnsbuf[spr_shadow].tile;
13685
13686 if(get_bit(quest_rules,qr_NEWENEMYTILES))
13687 {
13688 shadowtile+=f2;
13689 }
13690 else
13691 {
13692 shadowtile+=f2?1:0;
13693 }
13694 }
13695 if(!shadow_overpit(this))
13696 enemy::drawshadow(dest, translucent);
13697 yofs=tempy;
13698 }
13699
13700 4 int32_t eStalfos::takehit(weapon *w)
13701 {
13702 4 int32_t wpnId = w->id;
13703 4 int32_t wpnDir = w->dir;
13704
13705
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if(wpnId==wHammer && shield && (flags & guy_bkshield)
13706 && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
13707 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
13708 {
13709 shield = false;
13710 flags &= ~(inv_left|inv_right|inv_back|inv_front);
13711
13712 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
13713 o_tile=s_tile;
13714 }
13715
13716 4 int32_t ret = enemy::takehit(w);
13717
13718
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
4 if(sclk && dmisc2==e2tSPLITHIT)
13719 sclk+=128; //Fuck these arbitrary values with no explanation. Fuck vires, too. -Z
13720
13721 4 return ret;
13722 }
13723
13724 void eStalfos::charge_attack()
13725 {
13726 if(slide())
13727 return;
13728
13729 if(clk<0 || dir<0 || stunclk || watch || ceiling || frozenclock )
13730 return;
13731
13732 if(clk3<=0)
13733 {
13734 fix_coords(true);
13735
13736 if(!dashing)
13737 {
13738 int32_t ldir = lined_up(7,false);
13739
13740 if(ldir!=-1 && canmove(ldir,false))
13741 {
13742 dir=ldir;
13743 dashing=true;
13744 step=zslongToFix(dstep*100)+1;
13745 }
13746 else newdir(4,0,0);
13747 }
13748
13749 if(!canmove(dir,false))
13750 {
13751 step=zslongToFix(dstep*100);
13752 newdir();
13753 dashing=false;
13754 }
13755
13756 zfix div = step;
13757
13758 if(div == 0)
13759 div = 1;
13760
13761 clk3=(int32_t)(16.0/div);
13762 return;
13763 }
13764
13765 move(step);
13766 --clk3;
13767 }
13768
13769 void eStalfos::vire_hop()
13770 {
13771 //if ( sclk > 0 ) return; //Don't hop during knockback.
13772
13773 // if(dmisc9!=e9tPOLSVOICE)
13774 // {
13775 // //if( slide() /*sclk!=0*/ && dmisc2==e2tSPLIT) //Vires with split on hit, only! -Z
13776 // if( sclk!=0 && dmisc2==e2tSPLIT) //Vires with split on hit, only! -Z
13777 // return; //the enemy should split if it is sliding!
13778 // //else sclk=0; //might need this here, too. -Z
13779 // }
13780 if(dmisc9!=e9tPOLSVOICE)
13781 {
13782 if(sclk!=0)
13783 {
13784 if (dmisc2==e2tSPLITHIT) return;
13785 //return;
13786 }
13787 }
13788 else sclk=0;
13789
13790 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock)
13791 return;
13792
13793 int32_t jump_width = (dmisc9==e9tPOLSVOICE) ? 2 : 1;
13794 int32_t jump_height = (dmisc9==e9tPOLSVOICE) ? 27 : 16;
13795
13796 y=floor_y;
13797
13798 if(clk3<=0)
13799 {
13800 fix_coords();
13801
13802 //z=0;
13803 //if we're not in the middle of a jump or if we can't complete the current jump in the current direction
13804 //if(clk2<=0 || !canmove(dir,(zfix)1,spw_floater,false) || (isSideViewGravity() && isOnSideviewPlatform()))
13805 if(clk2<=0 || !canmove(dir,(zfix)1,spw_floater,false) || (isSideViewGravity() && (isOnSideviewPlatform() || !(moveflags & FLAG_OBEYS_GRAV)))) //Vires in old quests
13806 newdir(rate,homing,dmisc9==e9tPOLSVOICE ? spw_floater : spw_none);
13807
13808 if(clk2<=0)
13809 {
13810 //z=0;
13811 if(!canmove(dir,(zfix)2,spw_none,false) || m_walkflag(x,y,spw_none, dir) || (zc_oldrand()&15)>=hrate)
13812 {
13813
13814 clk2=(wpn==ewBrang ? 1 : int32_t((16.0*jump_width)/step.getFloat()));
13815 /*if (dmisc9==e9tPOLSVOICE )
13816 {
13817 zprint2("polsvoice jump_width is: %d\n", jump_width);
13818 zprint2("polsvoice raw step is: %d\n", step);
13819 zprint2("polsvoice step.getInt() is: %d\n", step.getInt());
13820 zprint2("setting clk2 on polsvoice to: %d\n", clk2);
13821 }
13822 else
13823 {
13824 zprint2("vire jump_width is: %d\n", jump_width);
13825 zprint2("vire raw step is: %d\n", step);
13826 zprint2("vire step.getInt() is: %d\n", step.getInt());
13827 zprint2("setting clk2 on vire to: %d\n", clk2);
13828 }
13829 */
13830 }
13831 }
13832
13833 if(dmisc9!=e9tPOLSVOICE && dir>=left) //if we're moving left or right
13834 {
13835 clk2=int32_t((16.0*jump_width)/step.getFloat());
13836 }
13837
13838 clk3=int32_t(16.0/step.getFloat());
13839 }
13840
13841 --clk3;
13842
13843 if(dmisc9==e9tPOLSVOICE || clk2>0)
13844 move(step);
13845
13846 floor_y=y;
13847 clk2--;
13848
13849 //if we're in the middle of a jump
13850 if(clk2>0 && (dir>=left || dmisc9==e9tPOLSVOICE))
13851 {
13852 int32_t h = fixtoi(fixsin(itofix(clk2*128*step/(16*jump_width)))*jump_height);
13853
13854 if(get_bit(quest_rules,qr_ENEMIESZAXIS) && !(isSideViewGravity()))
13855 {
13856 if (moveflags & FLAG_USE_FAKE_Z) fakez=h;
13857 else z=h;
13858 }
13859 else
13860 {
13861 //y+=fixtoi(fixsin(itofix((clk2+1)*128*step/(16*jump_width)))*jump_height);
13862 //y-=h;
13863 y=floor_y-h;
13864 shadowdistance=h;
13865 }
13866 }
13867 else
13868 shadowdistance = 0;
13869 }
13870
13871 void eStalfos::eathero()
13872 {
13873 if(!hashero && Hero.getEaten()==0 && Hero.getAction() != hopping && Hero.getAction() != swimming)
13874 {
13875 hashero=true;
13876 y=floor_y;
13877 z=0;
13878
13879 if(Hero.isSwimming())
13880 {
13881 Hero.setX(x);
13882 Hero.setY(y);
13883 }
13884 else
13885 {
13886 x=Hero.getX();
13887 y=Hero.getY();
13888 }
13889
13890 clk2=0;
13891 }
13892 }
13893
13894 bool eStalfos::WeaponOut()
13895 {
13896 for(int32_t i=0; i<Ewpns.Count(); i++)
13897 {
13898 if(((weapon*)Ewpns.spr(i))->parentid==getUID() && Ewpns.spr(i)->id==ewBrang)
13899 {
13900 return true;
13901 }
13902
13903 /*if (bgsfx > 0 && guys.idCount(id) < 2) // count self
13904 stop_sfx(bgsfx);
13905 */
13906 }
13907
13908 return false;
13909 }
13910
13911 72 void eStalfos::KillWeapon()
13912 {
13913
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 52 times.
124 for(int32_t i=0; i<Ewpns.Count(); i++)
13914 {
13915
2/4
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
52 if(((weapon*)Ewpns.spr(i))->type==misc && Ewpns.spr(i)->id==ewBrang)
13916 {
13917 //only kill this Goriya's boomerang -DD
13918 if(((weapon *)Ewpns.spr(i))->parentid == getUID())
13919 {
13920 Ewpns.del(i);
13921 }
13922 }
13923 52 }
13924
13925
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if(wpn==ewBrang && !Ewpns.idCount(ewBrang))
13926 {
13927 stop_sfx(WAV_BRANG);
13928 }
13929 72 }
13930
13931 void eStalfos::break_shield()
13932 {
13933 if(!shield)
13934 return;
13935
13936 flags&=~(inv_front | inv_back | inv_left | inv_right);
13937 shield=false;
13938
13939 if(get_bit(quest_rules,qr_BRKNSHLDTILES))
13940 o_tile=s_tile;
13941 }
13942
13943 eKeese::eKeese(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
13944 {
13945 dir=(zc_oldrand()&7)+8;
13946 step=0;
13947 movestatus=1;
13948 if (dmisc1 != 1 && dmisc19 > 0)
13949 {
13950 step = dmisc19/100.0;
13951 movestatus = 1;
13952 }
13953 if (dmisc1 == 2) movestatus=2;
13954 c=0;
13955 SIZEflags = d->SIZEflags;
13956 if ( !(SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) ) hxofs=2;
13957 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
13958
13959 if ( !(SIZEflags&guyflagOVERRIDE_HIT_WIDTH) ) hxsz=12;
13960 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && d->hxsz >= 0 ) hxsz = d->hxsz;
13961
13962 if ( !(SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) ) hyofs=4;
13963 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
13964
13965 if ( !(SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) ) hysz=8;
13966 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && d->hysz >= 0 ) hysz = d->hysz;
13967
13968 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && d->txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
13969 //al_trace("->txsz:%i\n", d->txsz); Verified that this is setting the value. -Z
13970 // al_trace("Enemy txsz:%i\n", txsz);
13971 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && d->tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
13972
13973
13974 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && d->hzsz >= 0 ) hzsz = d->hzsz;
13975
13976 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
13977 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
13978 {
13979 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
13980 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
13981 }
13982
13983 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
13984 clk4=0;
13985 //nets;
13986 dummy_int[1]=0;
13987 }
13988
13989 bool eKeese::animate(int32_t index)
13990 {
13991 if(switch_hooked) return enemy::animate(index);
13992 if(fallclk||drownclk) return enemy::animate(index);
13993 if(dying)
13994 return Dead(index);
13995
13996 if(clk==0)
13997 {
13998 removearmos(x,y);
13999 }
14000
14001 if(dmisc1 == 1) //Walk style. 0 is keese, 1 is bat.
14002 {
14003 floater_walk(rate,hrate,dstep/100,(zfix)0,10,dmisc16,dmisc17);
14004 }
14005 else
14006 {
14007 if (dmisc18) floater_walk(rate,hrate,dstep/100,dmisc18/100.0,-1,dmisc16,dmisc17);
14008 else floater_walk(rate,hrate,dstep/100,dstep/1000,10,dmisc16,dmisc17);
14009 }
14010
14011 if(dmisc2 == e2tKEESETRIB)
14012 {
14013 if(++clk4==(dmisc20>0?dmisc20:256))
14014 {
14015 if(!m_walkflag(x,y,0, dir))
14016 {
14017 int32_t kids = guys.Count();
14018 bool success = false;
14019 int32_t id2=dmisc3;
14020 success = 0 != addenemy((zfix)x,(zfix)y,id2,-24);
14021
14022 if(success)
14023 {
14024 if(itemguy) // Hand down the carried item
14025 {
14026 guycarryingitem = guys.Count()-1;
14027 ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
14028 itemguy = false;
14029 }
14030
14031 ((enemy*)guys.spr(kids))->count_enemy = count_enemy;
14032 }
14033
14034 stop_bgsfx(index);
14035 return true;
14036 }
14037 else
14038 {
14039 clk4=0;
14040 }
14041 }
14042 }
14043 // Keese Tribbles stay on the ground, so there's no problem when they transform.
14044 else if(get_bit(quest_rules,qr_ENEMIESZAXIS) && !(isSideViewGravity()))
14045 {
14046 if (get_bit(quest_rules,qr_OLD_KEESE_Z_AXIS))
14047 {
14048 if (moveflags & FLAG_USE_FAKE_Z)
14049 {
14050 fakez=int32_t(step/zslongToFix(dstep*100));
14051 // Some variance in keese flight heights when away from Hero
14052 fakez+=int32_t(step*zc_max(zfix(0),(distance(x,y,HeroX(),HeroY())-128)/10));
14053
14054 }
14055 else
14056 {
14057 z=int32_t(step/zslongToFix(dstep*100));
14058 // Some variance in keese flight heights when away from Hero
14059 z+=int32_t(step*zc_max(zfix(0),(distance(x,y,HeroX(),HeroY())-128)/10));
14060 }
14061 }
14062 else
14063 {
14064 if (moveflags & FLAG_USE_FAKE_Z)
14065 {
14066 fakez=int32_t(step/zslongToFix(dstep*100));
14067 // Some variance in keese flight heights when away from Hero
14068 fakez+=int32_t(step*zc_max(zfix(0),(distance(x,y,HeroX(),HeroY())-40)/4));
14069
14070 }
14071 else
14072 {
14073 z=int32_t(step/zslongToFix(dstep*100));
14074 // Some variance in keese flight heights when away from Hero
14075 z+=int32_t(step*zc_max(zfix(0),(distance(x,y,HeroX(),HeroY())-40)/4));
14076 }
14077 }
14078 }
14079
14080 return enemy::animate(index);
14081 }
14082
14083 void eKeese::drawshadow(BITMAP *dest, bool translucent)
14084 {
14085 int32_t tempy=yofs;
14086 flip = 0;
14087 shadowtile = wpnsbuf[spr_shadow].tile+posframe;
14088
14089 yofs+=zc_min(int32_t(step/zslongToFix(dstep*10)), 8);
14090 if(!get_bit(quest_rules,qr_ENEMIESZAXIS))
14091 {
14092 yofs+=int32_t(step/zslongToFix(dstep*10));
14093 }
14094
14095 if(!shadow_overpit(this) && (!get_bit(quest_rules,qr_ENEMIESZAXIS) || step > 0))
14096 enemy::drawshadow(dest, translucent);
14097 yofs=tempy;
14098 }
14099
14100 void eKeese::draw(BITMAP *dest)
14101 {
14102 update_enemy_frame();
14103 enemy::draw(dest);
14104 }
14105
14106 void eWizzrobe::submerge(bool set)
14107 {
14108 if(get_bit(quest_rules,qr_OLD_WIZZROBE_SUBMERGING))
14109 {
14110 hxofs = set?1000:0;
14111 return;
14112 }
14113 if(submerged == set) return;
14114 submerged = set;
14115 if(set)
14116 hxofs+=1000;
14117 else hxofs -= 1000;
14118 }
14119 eWizzrobe::eWizzrobe(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
14120 {
14121 hxofs = 0;
14122 submerged = false;
14123 switch(dmisc1)
14124 {
14125 case 0:
14126 submerge(true);
14127 fading=fade_invisible;
14128 // Set clk to just before the 'reappear' threshold
14129 clk=zc_min(clk+(146+zc_max(0,dmisc5))+14,(146+zc_max(0,dmisc5))-1);
14130 break;
14131
14132 default:
14133 dir=(loadside==right)?right:left;
14134 misc=-3;
14135 break;
14136 }
14137
14138 //netst+2880;
14139 charging=false;
14140 firing=false;
14141 fclk=0;
14142 if(!dmisc1) frate=1200+146; //1200 = 20 seconds
14143 SIZEflags = d->SIZEflags;
14144 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && d->txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
14145 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
14146 // al_trace("Enemy txsz:%i\n", txsz);
14147 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && d->tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
14148 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && d->hxsz >= 0 ) hxsz = d->hxsz;
14149 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && d->hysz >= 0 ) hysz = d->hysz;
14150 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && d->hzsz >= 0 ) hzsz = d->hzsz;
14151 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 )
14152 {
14153 hxofs = (submerged?hxofs:0)+d->hxofs;
14154 }
14155 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
14156 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
14157 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
14158 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
14159 {
14160 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
14161 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
14162 }
14163
14164 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
14165 }
14166
14167 bool eWizzrobe::animate(int32_t index)
14168 {
14169 if(switch_hooked) return enemy::animate(index);
14170 if(fallclk||drownclk) return enemy::animate(index);
14171 if(dying)
14172 {
14173 return Dead(index);
14174 }
14175
14176 if(clk==0)
14177 {
14178 removearmos(x,y);
14179 }
14180
14181 if(dmisc1) // Floating
14182 {
14183 wizzrobe_attack();
14184 }
14185 else // Teleporting
14186 {
14187 if(watch || (!get_bit(quest_rules, qr_WIZZROBES_DONT_OBEY_STUN) && stunclk))
14188 {
14189 fading=0;
14190 submerge(false);
14191 solid_update(false);
14192 }
14193 else switch(clk)
14194 {
14195 case 0:
14196 if(!dmisc2)
14197 {
14198 // Wizzrobe Misc4 controls whether wizzrobes can teleport on top of solid combos,
14199 // but should not appear on dungeon walls.
14200 if ( FFCore.getQuestHeaderInfo(vZelda) <= 0x190 ) place_on_axis(true, false); //1.84, and probably 1.90 wizzrobes should NEVER appear in dungeon walls.-Z (1.84 confirmed, 15th January, 2019 by Chris Miller).
14201 else if (editorflags&ENEMY_FLAG5)
14202 {
14203 //2.10 Windrobe
14204 //randomise location and face Hero
14205 int32_t t=0;
14206 bool placed=false;
14207
14208 while(!placed && t<160)
14209 {
14210 if(isdungeon())
14211 {
14212 x=((zc_oldrand()%12)+2)*16;
14213 y=((zc_oldrand()%7)+2)*16;
14214 }
14215 else
14216 {
14217 x=((zc_oldrand()%14)+1)*16;
14218 y=((zc_oldrand()%9)+1)*16;
14219 }
14220
14221 if(!m_walkflag(x,y,spw_door, dir)&&((abs(x-Hero.getX())>=32)||(abs(y-Hero.getY())>=32)))
14222 {
14223 placed=true;
14224 }
14225
14226 ++t;
14227 }
14228
14229 if(abs(x-Hero.getX())<abs(y-Hero.getY()))
14230 {
14231 if(y<Hero.getY())
14232 {
14233 dir=down;
14234 }
14235 else
14236 {
14237 dir=up;
14238 }
14239 }
14240 else
14241 {
14242 if(x<Hero.getX())
14243 {
14244 dir=right;
14245 }
14246 else
14247 {
14248 dir=left;
14249 }
14250 }
14251
14252 if(!placed) // can't place him, he's gone
14253 return true;
14254
14255
14256 //wizzrobe_attack(); //Complaint about 2.10 Windrobes not behaving as they did in 2.10. Let's try it this way. -Z
14257 //wizzrobe_attack_for_real(); //doing this makes them fire twice. The rest is correct.
14258 }
14259 else place_on_axis(true, dmisc4!=0);
14260 }
14261 else
14262 {
14263 int32_t t=0;
14264 bool placed=false;
14265
14266 while(!placed && t<160)
14267 {
14268 if(isdungeon())
14269 {
14270 x=((zc_oldrand()%12)+2)*16;
14271 y=((zc_oldrand()%7)+2)*16;
14272 }
14273 else
14274 {
14275 x=((zc_oldrand()%14)+1)*16;
14276 y=((zc_oldrand()%9)+1)*16;
14277 }
14278
14279 if(!m_walkflag(x,y,spw_door, dir)&&((abs(x-Hero.getX())>=32)||(abs(y-Hero.getY())>=32)))
14280 {
14281 placed=true;
14282 }
14283
14284 ++t;
14285 }
14286
14287 if(abs(x-Hero.getX())<abs(y-Hero.getY()))
14288 {
14289 if(y<Hero.getY())
14290 {
14291 dir=down;
14292 }
14293 else
14294 {
14295 dir=up;
14296 }
14297 }
14298 else
14299 {
14300 if(x<Hero.getX())
14301 {
14302 dir=right;
14303 }
14304 else
14305 {
14306 dir=left;
14307 }
14308 }
14309
14310 if(!placed) // can't place him, he's gone
14311 return true;
14312 }
14313
14314 fading=fade_flicker;
14315 submerge(false);
14316 solid_update(false);
14317 break;
14318
14319 case 64:
14320 fading=0;
14321 charging=true;
14322 break;
14323
14324 case 73:
14325 charging=false;
14326 firing=40;
14327 break;
14328
14329 case 83:
14330 wizzrobe_attack_for_real();
14331 break;
14332
14333 case 119:
14334 firing=false;
14335 charging=true;
14336 break;
14337
14338 case 128:
14339 fading=fade_flicker;
14340 charging=false;
14341 break;
14342
14343 case 146:
14344 fading=fade_invisible;
14345 submerge(true);
14346 solid_update(false);
14347
14348 [[fallthrough]];
14349 default:
14350 if(clk>=(146+zc_max(0,dmisc5)))
14351 clk=-1;
14352
14353 break;
14354 }
14355 }
14356
14357 return enemy::animate(index);
14358 }
14359
14360 void eWizzrobe::wizzrobe_attack_for_real()
14361 {
14362 if(wpn==0) // Edited enemies
14363 return;
14364
14365 if(dmisc2 == 0) //normal weapon
14366 {
14367 addEwpn(x,y,z,wpn,0,wdp,dir,getUID(), 0, fakez);
14368 sfx(WAV_WAND,pan(int32_t(x)));
14369 }
14370 else if(dmisc2 == 1) // ring of fire
14371 {
14372 addEwpn(x,y,z,wpn,0,wdp,up,getUID(), 0, fakez);
14373 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14374 addEwpn(x,y,z,wpn,0,wdp,down,getUID(), 0, fakez);
14375 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14376 addEwpn(x,y,z,wpn,0,wdp,left,getUID(), 0, fakez);
14377 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14378 addEwpn(x,y,z,wpn,0,wdp,right,getUID(), 0, fakez);
14379 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14380 addEwpn(x,y,z,wpn,0,wdp,l_up,getUID(), 0, fakez);
14381 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14382 addEwpn(x,y,z,wpn,0,wdp,r_up,getUID(), 0, fakez);
14383 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14384 addEwpn(x,y,z,wpn,0,wdp,l_down,getUID(), 0, fakez);
14385 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14386 addEwpn(x,y,z,wpn,0,wdp,r_down,getUID(), 0, fakez);
14387 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
14388 sfx(WAV_FIRE,pan(int32_t(x)));
14389 if (get_bit(quest_rules, qr_8WAY_SHOT_SFX)) sfx(WAV_FIRE,pan(int32_t(x)));
14390 else
14391 {
14392 switch(wpn)
14393 {
14394 case ewFireball: sfx(40,pan(int32_t(x))); break;
14395
14396 case ewArrow: sfx(1,pan(int32_t(x))); break; //Ghost.zh has 0?
14397 case ewBrang: sfx(4,pan(int32_t(x))); break; //Ghost.zh has 0?
14398 case ewSword: sfx(20,pan(int32_t(x))); break; //Ghost.zh has 0?
14399 case ewRock: sfx(51,pan(int32_t(x))); break;
14400 case ewMagic: sfx(32,pan(int32_t(x))); break;
14401 case ewBomb: sfx(3,pan(int32_t(x))); break; //Ghost.zh has 0?
14402 case ewSBomb: sfx(3,pan(int32_t(x))); break; //Ghost.zh has 0?
14403 case ewLitBomb: sfx(21,pan(int32_t(x))); break; //Ghost.zh has 0?
14404 case ewLitSBomb: sfx(21,pan(int32_t(x))); break; //Ghost.zh has 0?
14405 case ewFireTrail: sfx(13,pan(int32_t(x))); break;
14406 case ewFlame: sfx(13,pan(int32_t(x))); break;
14407 case ewWind: sfx(32,pan(int32_t(x))); break;
14408 case ewFlame2: sfx(13,pan(int32_t(x))); break;
14409 case ewFlame2Trail: sfx(13,pan(int32_t(x))); break;
14410 case ewIce: sfx(44,pan(int32_t(x))); break;
14411 case ewFireball2: sfx(40,pan(int32_t(x))); break; //fireball (rising)
14412 default: sfx(WAV_FIRE,pan(int32_t(x))); break;
14413
14414 }
14415 }
14416 }
14417 else if(dmisc2==2) // summons specific enemy
14418 {
14419 int32_t bc=0;
14420
14421 for(int32_t gc=0; gc<guys.Count(); gc++)
14422 {
14423 if((((enemy*)guys.spr(gc))->id) == dmisc3)
14424 {
14425 ++bc;
14426 }
14427 }
14428
14429 if(bc<=40)
14430 {
14431 int32_t kids = guys.Count();
14432 int32_t bats=(zc_oldrand()%3)+1;
14433
14434 for(int32_t i=0; i<bats; i++)
14435 {
14436 // Summon bats (or anything)
14437 if(addchild(x,y,dmisc3,-10, this->script_UID))
14438 ((enemy*)guys.spr(kids+i))->count_enemy = false;
14439 }
14440
14441 sfx(WAV_FIRE,pan(int32_t(x)));
14442 }
14443 }
14444 else if(dmisc2==3) //summon from layer
14445 {
14446 if(count_layer_enemies()==0)
14447 {
14448 return;
14449 }
14450
14451 int32_t kids = guys.Count();
14452
14453 if(kids<200)
14454 {
14455 int32_t newguys=(zc_oldrand()%3)+1;
14456 bool summoned=false;
14457
14458 for(int32_t i=0; i<newguys; i++)
14459 {
14460 int32_t id2=vbound(random_layer_enemy(),eSTART,eMAXGUYS-1);
14461 int32_t x2=0;
14462 int32_t y2=0;
14463
14464 for(int32_t k=0; k<20; ++k)
14465 {
14466 x2=16*((zc_oldrand()%12)+2);
14467 y2=16*((zc_oldrand()%7)+2);
14468
14469 if(!m_walkflag(x2,y2,0, dir) && (abs(x2-Hero.getX())>=32 || abs(y2-Hero.getY())>=32))
14470 {
14471 if(addchild(x2,y2,get_bit(quest_rules,qr_ENEMIESZAXIS) ? 64 : 0,id2,-10, this->script_UID))
14472 {
14473 ((enemy*)guys.spr(kids+i))->count_enemy = false;
14474 if (get_bit(quest_rules,qr_ENEMIESZAXIS) && (((enemy*)guys.spr(kids+i))->moveflags & FLAG_USE_FAKE_Z))
14475 {
14476 ((enemy*)guys.spr(kids+i))->fakez = 64;
14477 ((enemy*)guys.spr(kids+i))->z = 0;
14478 }
14479 }
14480
14481 summoned=true;
14482 break;
14483 }
14484 }
14485 }
14486
14487 if(summoned)
14488 {
14489 sfx(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,pan(int32_t(x)));
14490 }
14491 }
14492 }
14493 }
14494
14495
14496 void eWizzrobe::wizzrobe_attack()
14497 {
14498 if(clk<0 || dying || stunclk || watch || ceiling || frozenclock)
14499 return;
14500
14501 if(clk3<=0 || ((clk3&31)==0 && !canmove(dir,(zfix)1,spw_door,false) && !misc))
14502 {
14503 fix_coords();
14504
14505 switch(misc)
14506 {
14507 case 1: //walking
14508 if(!m_walkflag(x,y,spw_door, dir))
14509 misc=0;
14510 else
14511 {
14512 clk3=16;
14513
14514 if(!canmove(dir,(zfix)1,spw_wizzrobe,false))
14515 {
14516 wizzrobe_newdir(0);
14517 }
14518 }
14519
14520 break;
14521
14522 case 2: //phasing
14523 {
14524 int32_t jx=x;
14525 int32_t jy=y;
14526 int32_t jdir=-1;
14527
14528 switch(zc_oldrand()&7)
14529 {
14530 case 0:
14531 jx-=32;
14532 jy-=32;
14533 jdir=15;
14534 break;
14535
14536 case 1:
14537 jx+=32;
14538 jy-=32;
14539 jdir=9;
14540 break;
14541
14542 case 2:
14543 jx+=32;
14544 jy+=32;
14545 jdir=11;
14546 break;
14547
14548 case 3:
14549 jx-=32;
14550 jy+=32;
14551 jdir=13;
14552 break;
14553 }
14554
14555 if(jdir>0 && jx>=32 && jx<=208 && jy>=32 && jy<=128)
14556 {
14557 misc=3;
14558 clk3=32;
14559 dir=jdir;
14560 break;
14561 }
14562 }
14563 [[fallthrough]];
14564 case 3:
14565 dir&=3;
14566 misc=0;
14567 [[fallthrough]];
14568 case 0:
14569 wizzrobe_newdir(64);
14570 [[fallthrough]];
14571 default:
14572 if(!canmove(dir,(zfix)1,spw_door,false))
14573 {
14574 if(canmove(dir,(zfix)15,spw_wizzrobe,false))
14575 {
14576 misc=1;
14577 clk3=16;
14578 }
14579 else
14580 {
14581 wizzrobe_newdir(64);
14582 misc=0;
14583 clk3=32;
14584 }
14585 }
14586 else
14587 {
14588 clk3=32;
14589 }
14590
14591 break;
14592 }
14593
14594 if(misc<0)
14595 ++misc;
14596 }
14597
14598 --clk3;
14599
14600 switch(misc)
14601 {
14602 case 1:
14603 case 3:
14604 step=1;
14605 break;
14606
14607 case 2:
14608 step=0;
14609 break;
14610
14611 default:
14612 step=0.5;
14613 break;
14614
14615 }
14616
14617 move(step);
14618
14619 // if(d->misc1 && misc<=0 && clk3==28)
14620 if(dmisc1 && misc<=0 && clk3==28)
14621 {
14622 if(dmisc2 != 1)
14623 {
14624 if(lined_up(8,false) == dir)
14625 {
14626 // addEwpn(x,y,z,wpn,0,wdp,dir,getUID());
14627 // sfx(WAV_WAND,pan(int32_t(x)));
14628 wizzrobe_attack_for_real();
14629 fclk=30;
14630 }
14631 }
14632 else
14633 {
14634 if((zc_oldrand()%500)>=400)
14635 {
14636 wizzrobe_attack_for_real();
14637 fclk=30;
14638 }
14639 }
14640 }
14641
14642 if(misc==0 && (zc_oldrand()&127)==0)
14643 misc=2;
14644
14645 if(misc==2 && clk3==4)
14646 fix_coords();
14647
14648 if(!(charging||firing)) //should never be charging or firing for these wizzrobes
14649 {
14650 if(fclk>0)
14651 {
14652 --fclk;
14653 }
14654 }
14655
14656 }
14657
14658 void eWizzrobe::wizzrobe_newdir(int32_t homing)
14659 {
14660 // Wizzrobes shouldn't move to the edge of the screen;
14661 // if they're already there, they should move toward the center
14662 if(x<32)
14663 dir=right;
14664 else if(x>=224)
14665 dir=left;
14666 else if(y<32)
14667 dir=down;
14668 else if(y>=144)
14669 dir=up;
14670 else
14671 newdir(4,homing,spw_wizzrobe);
14672 }
14673
14674 void eWizzrobe::draw(BITMAP *dest)
14675 {
14676 // if(d->misc1 && (misc==1 || misc==3) && (clk3&1) && hp>0 && !watch && !stunclk) // phasing
14677 if(dmisc1 && (misc==1 || misc==3) && (clk3&1) && hp>0 && !watch && !stunclk && !frozenclock) // phasing
14678 return;
14679
14680 int32_t tempint=dummy_int[1];
14681 bool tempbool1=dummy_bool[1];
14682 bool tempbool2=dummy_bool[2];
14683 dummy_int[1]=fclk;
14684 dummy_bool[1]=charging;
14685 dummy_bool[2]=firing;
14686 update_enemy_frame();
14687 dummy_int[1]=tempint;
14688 dummy_bool[1]=tempbool1;
14689 dummy_bool[2]=tempbool2;
14690 enemy::draw(dest);
14691 }
14692
14693 /*********************************/
14694 /********** Bosses ***********/
14695 /*********************************/
14696
14697 eDodongo::eDodongo(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
14698 {
14699 fading=fade_flash_die;
14700 //nets+5120;
14701 if(dir==down&&y>=128)
14702 {
14703 dir=up;
14704 }
14705
14706 if(dir==right&&x>=208)
14707 {
14708 dir=left;
14709 }
14710 SIZEflags = d->SIZEflags;
14711 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
14712 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
14713 // al_trace("Enemy txsz:%i\n", txsz);
14714 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
14715 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
14716 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
14717 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
14718 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
14719 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
14720 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
14721 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
14722 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
14723 {
14724 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
14725 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
14726 }
14727
14728 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)zofs;
14729 }
14730
14731 bool eDodongo::animate(int32_t index)
14732 {
14733 if(switch_hooked) return enemy::animate(index);
14734 if(dying)
14735 {
14736 return Dead(index);
14737 }
14738
14739 if(clk==0)
14740 {
14741 removearmos(x,y);
14742 }
14743
14744 if(clk2) // ate a bomb
14745 {
14746 if(--clk2==0)
14747 hp-=misc; // store bomb's power in misc
14748 }
14749 else
14750 constant_walk(rate,homing,spw_clipright);
14751
14752 hxsz = (dir<=down) ? 16 : 32;
14753 // hysz = (dir>=left) ? 16 : 32;
14754
14755 return enemy::animate(index);
14756 }
14757
14758 void eDodongo::draw(BITMAP *dest)
14759 {
14760 tile=o_tile;
14761
14762 if(clk<0)
14763 {
14764 enemy::drawzcboss(dest);
14765 return;
14766 }
14767
14768 update_enemy_frame();
14769 enemy::drawzcboss(dest);
14770
14771 if(dummy_int[1]!=0) //additional tiles
14772 {
14773 tile+=dummy_int[1]; //second tile is previous tile
14774 xofs-=16; //new xofs change
14775 enemy::drawzcboss(dest);
14776 xofs+=16;
14777 }
14778
14779 }
14780
14781 int32_t eDodongo::takehit(weapon *w)
14782 {
14783 int32_t wpnId = w->id;
14784 int32_t power = w->power;
14785 int32_t wpnx = w->x;
14786 int32_t wpny = w->y;
14787
14788 if(dying || clk<0 || clk2>0 || (superman && !(superman>1 && wpnId==wSBomb)))
14789 return 0;
14790
14791 switch(wpnId)
14792 {
14793 case wPhantom:
14794 return 0;
14795
14796 case wFire:
14797 case wBait:
14798 case wWhistle:
14799 case wWind:
14800 case wSSparkle:
14801 case wFSparkle:
14802 return 0;
14803
14804 case wLitBomb:
14805 case wLitSBomb:
14806 if(abs(wpnx-((dir==right)?x+16:x)) > 7 || abs(wpny-y) > 7)
14807 return 0;
14808
14809 clk2=96;
14810 misc=power;
14811
14812 if(wpnId==wLitSBomb)
14813 item_set=isSBOMB100;
14814
14815 return 1;
14816
14817 case wBomb:
14818 case wSBomb:
14819 if(abs(wpnx-((dir==right)?x+16:x)) > 8 || abs(wpny-y) > 8)
14820 return 0;
14821
14822 stunclk=160;
14823 misc=wpnId; // store wpnId
14824 return 1;
14825
14826 case wSword:
14827 if(stunclk)
14828 {
14829 sfx(WAV_EHIT,pan(int32_t(x)));
14830 hp=0;
14831 item_set = (misc==wSBomb) ? isSBOMB100 : isBOMB100;
14832 fading=0; // don't flash
14833 return 1;
14834 }
14835
14836 [[fallthrough]];
14837 default:
14838 sfx(WAV_CHINK,pan(int32_t(x)));
14839 }
14840
14841 return 1;
14842 }
14843
14844 eDodongo2::eDodongo2(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
14845 {
14846 fading=fade_flash_die;
14847 //nets+5180;
14848 previous_dir=-1;
14849 if(dir==down&&y>=128)
14850 {
14851 dir=up;
14852 }
14853
14854 if(dir==right&&x>=208)
14855 {
14856 dir=left;
14857 }
14858 SIZEflags = d->SIZEflags;
14859 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
14860 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
14861 // al_trace("Enemy txsz:%i\n", txsz);
14862 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
14863 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
14864 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
14865 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
14866 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
14867 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
14868 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
14869 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
14870 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
14871 {
14872 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
14873 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
14874 }
14875
14876 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)zofs;
14877 }
14878
14879 bool eDodongo2::animate(int32_t index)
14880 {
14881 if(switch_hooked) return enemy::animate(index);
14882 if(dying)
14883 {
14884 return Dead(index);
14885 }
14886
14887 if(clk==0)
14888 {
14889 removearmos(x,y);
14890 }
14891
14892 if(clk2) // ate a bomb
14893 {
14894 if(--clk2==0)
14895 hp-=misc; // store bomb's power in misc
14896 }
14897 else
14898 constant_walk(rate,homing,spw_clipbottomright);
14899
14900 hxsz = (dir<=down) ? 16 : 32;
14901 hysz = (dir>=left) ? 16 : 32;
14902 hxofs=(dir>=left)?-8:0;
14903 hyofs=(dir<left)?-8:0;
14904
14905 return enemy::animate(index);
14906 }
14907
14908 void eDodongo2::draw(BITMAP *dest)
14909 {
14910 if(clk<0)
14911 {
14912 enemy::drawzcboss(dest);
14913 return;
14914 }
14915
14916 int32_t tempx=xofs;
14917 int32_t tempy=yofs;
14918 update_enemy_frame();
14919 enemy::drawzcboss(dest);
14920 tile+=dummy_int[1]; //second tile change
14921 xofs+=dummy_int[2]; //new xofs change
14922 yofs+=dummy_int[3]; //new yofs change
14923 enemy::drawzcboss(dest);
14924 xofs=tempx;
14925 yofs=tempy;
14926 }
14927
14928 int32_t eDodongo2::takehit(weapon *w)
14929 {
14930 int32_t wpnId = w->id;
14931 int32_t power = w->power;
14932 int32_t wpnx = w->x;
14933 int32_t wpny = w->y;
14934
14935 if(dying || clk<0 || clk2>0 || superman)
14936 return 0;
14937
14938 switch(wpnId)
14939 {
14940 case wPhantom:
14941 return 0;
14942
14943 case wFire:
14944 case wBait:
14945 case wWhistle:
14946 case wWind:
14947 case wSSparkle:
14948 case wFSparkle:
14949 return 0;
14950
14951 case wLitBomb:
14952 case wLitSBomb:
14953 switch(dir)
14954 {
14955 case up:
14956 if(abs(wpnx-x) > 7 || abs(wpny-(y-8)) > 7)
14957 return 0;
14958
14959 break;
14960
14961 case down:
14962 if(abs(wpnx-x) > 7 || abs(wpny-(y+8)) > 7)
14963 return 0;
14964
14965 break;
14966
14967 case left:
14968 if(abs(wpnx-(x-8)) > 7 || abs(wpny-y) > 7)
14969 return 0;
14970
14971 break;
14972
14973 case right:
14974 if(abs(wpnx-(x+8)) > 7 || abs(wpny-y) > 7)
14975 return 0;
14976
14977 break;
14978 }
14979
14980 // if(abs(wpnx-((dir==right)?x+8:(dir==left)?x-8:0)) > 7 || abs(wpny-((dir==down)?y+8:(dir==up)?y-8:0)) > 7)
14981 // return 0;
14982 clk2=96;
14983 misc=power;
14984
14985 if(wpnId==wLitSBomb)
14986 item_set=isSBOMB100;
14987
14988 return 1;
14989
14990 case wBomb:
14991 case wSBomb:
14992 switch(dir)
14993 {
14994 case up:
14995 if(abs(wpnx-x) > 7 || abs(wpny-(y-8)) > 7)
14996 return 0;
14997
14998 break;
14999
15000 case down:
15001 if(abs(wpnx-x) > 7 || abs(wpny-(y+8)) > 7)
15002 return 0;
15003
15004 break;
15005
15006 case left:
15007 if(abs(wpnx-(x-8)) > 7 || abs(wpny-y) > 7)
15008 return 0;
15009
15010 break;
15011
15012 case right:
15013 if(abs(wpnx-(x+8)) > 7 || abs(wpny-y) > 7)
15014 return 0;
15015
15016 break;
15017 }
15018
15019 stunclk=160;
15020 misc=wpnId; // store wpnId
15021 return 1;
15022
15023 case wSword:
15024 if(stunclk)
15025 {
15026 sfx(WAV_EHIT,pan(int32_t(x)));
15027 hp=0;
15028 item_set = (misc==wSBomb) ? isSBOMB100 : isBOMB100;
15029 fading=0; // don't flash
15030 return 1;
15031 }
15032
15033 [[fallthrough]];
15034 default:
15035 sfx(WAV_CHINK,pan(int32_t(x)));
15036 }
15037
15038 return 1;
15039 }
15040
15041 eAquamentus::eAquamentus(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)//enemy((zfix)176,(zfix)64,Id,Clk)
15042 {
15043 //these are here to bypass compiler warnings about unused arguments
15044 if ( !(editorflags & ENEMY_FLAG5) )
15045 {
15046 x = dmisc1 ? 64 : 176;
15047 y = 64;
15048 }
15049 else { x = X; y = Y; }
15050
15051 //nets+5940;
15052 if(get_bit(quest_rules,qr_NEWENEMYTILES))
15053 {
15054 }
15055 else
15056 {
15057 if(dmisc1)
15058 {
15059 flip=1;
15060 }
15061 }
15062
15063 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset)+1;
15064 clk3=32;
15065 clk2=0;
15066 clk4=clk;
15067 dir=left;
15068 SIZEflags = d->SIZEflags;
15069 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
15070 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
15071 // al_trace("Enemy txsz:%i\n", txsz);
15072 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
15073 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
15074 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
15075 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
15076 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
15077 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
15078 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
15079 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
15080 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
15081 {
15082 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
15083 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
15084 }
15085
15086 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
15087 }
15088
15089 bool eAquamentus::animate(int32_t index)
15090 {
15091 if(switch_hooked) return enemy::animate(index);
15092 if(dying)
15093 return Dead(index);
15094
15095 // fbx=x+((id==eRAQUAM)?4:-4);
15096 if(clk==0)
15097 {
15098 removearmos(x,y);
15099 }
15100
15101 fbx=x;
15102
15103 /*
15104 if (get_bit(quest_rules,qr_NEWENEMYTILES)&&id==eLAQUAM)
15105 {
15106 fbx+=16;
15107 }
15108 */
15109 if(--clk3==0)
15110 {
15111 // addEwpn(fbx,y,z,ewFireball,0,d->wdp,up+1);
15112 // addEwpn(fbx,y,z,ewFireball,0,d->wdp,0);
15113 // addEwpn(fbx,y,z,ewFireball,0,d->wdp,down+1);
15114 addEwpn(fbx,y,z,wpn,2,wdp,up,getUID(), 0, fakez);
15115 addEwpn(fbx,y,z,wpn,2,wdp,8,getUID(), 0, fakez);
15116 addEwpn(fbx,y,z,wpn,2,wdp,down,getUID(), 0, fakez);
15117 sfx(wpnsfx(wpn),pan(int32_t(x)));
15118 }
15119
15120 if(clk3<-80 && !(zc_oldrand()&63))
15121 {
15122 clk3=32;
15123 }
15124
15125 if(!((clk4+1)&63))
15126 {
15127 int32_t d2=(zc_oldrand()%3)+1;
15128
15129 if(d2>=left)
15130 {
15131 dir=d2;
15132 }
15133
15134 if(dmisc1)
15135 {
15136 if(x<=40)
15137 {
15138 dir=right;
15139 }
15140
15141 if(x>=104)
15142 {
15143 dir=left;
15144 }
15145 }
15146 else
15147 {
15148 if(x<=136)
15149 {
15150 dir=right;
15151 }
15152
15153 if(x>=200)
15154 {
15155 dir=left;
15156 }
15157 }
15158 }
15159
15160 if(clk4>=-1 && !((clk4+1)&7))
15161 {
15162 if(dir==left)
15163 {
15164 x-=1;
15165 }
15166 else
15167 {
15168 x+=1;
15169 }
15170 }
15171
15172 clk4=(clk4+1)%256;
15173
15174 return enemy::animate(index);
15175 }
15176
15177 void eAquamentus::draw(BITMAP *dest)
15178 {
15179 if(get_bit(quest_rules,qr_NEWENEMYTILES))
15180 {
15181 xofs=(dmisc1?-16:0);
15182 if ( do_animation ) tile=o_tile+((clk&24)>>2)+(clk3>-32?(clk3>0?40:80):0);
15183
15184 if(dying)
15185 {
15186 xofs=0;
15187 enemy::draw(dest);
15188 }
15189 else
15190 {
15191 drawblock(dest,15);
15192 }
15193 }
15194 else
15195 {
15196 int32_t xblockofs=((dmisc1)?-16:16);
15197 xofs=0;
15198
15199 if(clk<0 || dying)
15200 {
15201 enemy::draw(dest);
15202 return;
15203 }
15204 if ( do_animation )
15205 {
15206 // face (0=firing, 2=resting)
15207 tile=o_tile+((clk3>0)?0:2);
15208 enemy::draw(dest);
15209 // tail (
15210 tile=o_tile+((clk&16)?1:3);
15211 xofs=xblockofs;
15212 enemy::draw(dest);
15213 // body
15214 yofs+=16;
15215 xofs=0;
15216 tile=o_tile+((clk&16)?20:22);
15217 enemy::draw(dest);
15218 xofs=xblockofs;
15219 tile=o_tile+((clk&16)?21:23);
15220 enemy::draw(dest);
15221 yofs-=16;
15222 }
15223 else enemy::draw(dest);
15224 }
15225 }
15226
15227 bool eAquamentus::hit(weapon *w)
15228 {
15229 if(!(w->scriptcoldet&1) || w->fallclk || w->drownclk) return false;
15230
15231 switch(w->id)
15232 {
15233 case wBeam:
15234 case wRefBeam:
15235 case wMagic:
15236 hysz=32;
15237 }
15238
15239 bool ret = (dying || hclk>0) ? false : sprite::hit(w);
15240 hysz=16;
15241 return ret;
15242
15243 }
15244
15245 eGohma::eGohma(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk) // enemy((zfix)128,(zfix)48,Id,0)
15246 {
15247
15248 if ( !(editorflags & ENEMY_FLAG5) )
15249 {
15250 x = 128;
15251 y = 48;
15252 }
15253 else { x = X; y = Y; }
15254
15255 Clk=Clk;
15256 if(flags & guy_fadeflicker)
15257 {
15258 clk=0;
15259 superman = 1;
15260 fading=fade_flicker;
15261 if (!(editorflags&ENEMY_FLAG3)) count_enemy=false;
15262 }
15263 else if(flags & guy_fadeinstant)
15264 {
15265 clk=0;
15266 }
15267 hxofs=-16;
15268 hxsz=48;
15269 clk4=0;
15270 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset)+1;
15271 dir=zc_oldrand()%3+1;
15272 SIZEflags = d->SIZEflags;
15273 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
15274 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
15275 // al_trace("Enemy txsz:%i\n", txsz);
15276 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = tysz; if ( tysz > 1 ) extend = 3; }
15277 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = hxsz;
15278 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = hysz;
15279 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = hzsz;
15280 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = hxofs;
15281 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = hyofs;
15282 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
15283 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)xofs;
15284 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
15285 {
15286 yofs = (int32_t)yofs; //This seems to be setting to +48 or something with any value set?! -Z
15287 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
15288 }
15289
15290 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)zofs;
15291
15292 //nets+5340;
15293 }
15294
15295 bool eGohma::animate(int32_t index)
15296 {
15297 if(switch_hooked) return enemy::animate(index);
15298 if(dying)
15299 return Dead(index);
15300
15301 if(fading)
15302 {
15303 if(++clk4 > 60)
15304 {
15305 clk4=0;
15306 superman=0;
15307 fading=0;
15308 clk=0;
15309
15310 }
15311 else return enemy::animate(index);
15312 }
15313
15314 if(clk==0)
15315 {
15316 removearmos(zc_max(x-16, zfix(0)),y);
15317 did_armos = false;
15318 removearmos(x,y);
15319 did_armos = false;
15320 removearmos(zc_min(x+16, zfix(255)),y);
15321 }
15322
15323 if(clk<0) return enemy::animate(index);
15324
15325 // Movement clk must be separate from animation clk because of the Clock item
15326 if(!watch)
15327 clk4++;
15328
15329 if((clk4&63)==0)
15330 {
15331 if(clk4&64)
15332 dir^=1;
15333 else
15334 dir=zc_oldrand()%3+1;
15335 }
15336
15337 if((clk&63)==3)
15338 {
15339 switch(dmisc1)
15340 {
15341 case 1:
15342 addEwpn(x,y+2,z,wpn,3,wdp,left,getUID(), 0, fakez);
15343 addEwpn(x,y+2,z,wpn,3,wdp,8,getUID(), 0, fakez);
15344 addEwpn(x,y+2,z,wpn,3,wdp,right,getUID(), 0, fakez);
15345 sfx(wpnsfx(wpn),pan(int32_t(x)));
15346 break;
15347
15348 default:
15349 if(dmisc1 != 1 && dmisc1 != 2)
15350 {
15351 addEwpn(x,y+2,z,wpn,3,wdp,8,getUID(), 0, fakez);
15352 sfx(wpnsfx(wpn),pan(int32_t(x)));
15353 sfx(wpnsfx(wpn),pan(int32_t(x)));
15354 }
15355
15356 break;
15357 }
15358 }
15359
15360 if((dmisc1 == 2)&& clk3>=16 && clk3<116)
15361 {
15362 if(!(clk3%8))
15363 {
15364 FireBreath(true);
15365 }
15366 }
15367
15368 if(clk4&1)
15369 move((zfix)1);
15370
15371 if(++clk3>=400)
15372 clk3=0;
15373
15374 return enemy::animate(index);
15375 }
15376
15377 void eGohma::draw(BITMAP *dest)
15378 {
15379 tile=o_tile;
15380
15381 if(clk<0 || dying)
15382 {
15383 enemy::drawzcboss(dest);
15384 return;
15385 }
15386
15387 if(get_bit(quest_rules,qr_NEWENEMYTILES))
15388 {
15389 ///if ( do_animation )
15390 //Yuck. Gohma can just not have this capability right now.
15391 // left side
15392 xofs=-16;
15393 flip=0;
15394 // if(clk&16) tile=180;
15395 // else { tile=182; flip=1; }
15396 tile+=(3*((clk&48)>>4));
15397 enemy::drawzcboss(dest);
15398
15399 // right side
15400 xofs=16;
15401 // tile=(180+182)-tile;
15402 tile=o_tile;
15403 tile+=(3*((clk&48)>>4))+2;
15404 enemy::drawzcboss(dest);
15405
15406 // body
15407 xofs=0; //Gohma may need more adjustments for SIZEflags. -Z 14 Aug 2020
15408 tile=o_tile;
15409
15410 // tile+=(3*((clk&24)>>3))+2;
15411 if(clk3<16)
15412 tile+=7;
15413 else if(clk3<116)
15414 tile+=10;
15415 else if(clk3<132)
15416 tile+=7;
15417 else
15418 tile+=((clk3-132)&24)?4:1;
15419
15420 enemy::drawzcboss(dest);
15421
15422 }
15423 else
15424 {
15425 // left side
15426 xofs=-16;
15427 flip=0;
15428
15429 if(!(clk&16))
15430 {
15431 tile+=2;
15432 flip=1;
15433 }
15434
15435 enemy::draw(dest);
15436
15437 // right side
15438 tile=o_tile;
15439 xofs=16;
15440
15441 if((clk&16)) tile+=2;
15442
15443 // tile=(180+182)-tile;
15444 enemy::draw(dest);
15445
15446 // body
15447 tile=o_tile;
15448 xofs=0;
15449
15450 if(clk3<16)
15451 tile+=4;
15452 else if(clk3<116)
15453 tile+=5;
15454 else if(clk3<132)
15455 tile+=4;
15456 else tile+=((clk3-132)&8)?3:1;
15457
15458 enemy::draw(dest);
15459
15460 }
15461 }
15462
15463 int32_t eGohma::takehit(weapon *w)
15464 {
15465 int32_t wpnId = w->id;
15466 int32_t power = w->power;
15467 int32_t wpnx = w->x;
15468 int32_t wpnDir = w->dir;
15469 int32_t def = defenditemclassNew(wpnId, &power, w);
15470
15471 if(def < 0)
15472 {
15473 if(!((wpnDir==up || wpnDir==l_up || wpnDir==r_up) && abs(int32_t(x)-wpnx)<=8 && clk3>=16 && clk3<116))
15474 {
15475 sfx(WAV_CHINK,pan(int32_t(x)));
15476 return 1;
15477 }
15478 }
15479
15480 return enemy::takehit(w);
15481 }
15482
15483 eLilDig::eLilDig(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
15484 {
15485 count_enemy=(id==(id&0xFFF));
15486 //nets+4360+(((id&0xFF)-eDIGPUP2)*40);
15487 SIZEflags = d->SIZEflags;
15488 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
15489 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
15490 // al_trace("Enemy txsz:%i\n", txsz);
15491 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
15492 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
15493 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
15494 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
15495 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
15496 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
15497 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
15498 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
15499 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
15500 {
15501 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
15502 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
15503 }
15504
15505 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
15506 }
15507
15508 bool eLilDig::animate(int32_t index)
15509 {
15510 if(switch_hooked) return enemy::animate(index);
15511 if(dying)
15512 return Dead(index);
15513
15514 if(clk==0)
15515 {
15516 removearmos(x,y);
15517 }
15518
15519 if(misc<=128)
15520 {
15521 if(!(++misc&31))
15522 step+=0.25;
15523 }
15524
15525 variable_walk_8(rate,homing,hrate,spw_floater);
15526 return enemy::animate(index);
15527 }
15528
15529 void eLilDig::draw(BITMAP *dest)
15530 {
15531 tile = o_tile;
15532 // tile = 160;
15533 int32_t fdiv = frate/4;
15534 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
15535 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
15536 efrate:((clk>=(frate>>1))?1:0);
15537
15538 if ( do_animation )
15539 {
15540 if(get_bit(quest_rules,qr_NEWENEMYTILES))
15541 {
15542 switch(dir-8) //directions get screwed up after 8. *shrug*
15543 {
15544 case up: //u
15545 flip=0;
15546 break;
15547
15548 case l_up: //d
15549 flip=0;
15550 tile+=4;
15551 break;
15552
15553 case l_down: //l
15554 flip=0;
15555 tile+=8;
15556 break;
15557
15558 case left: //r
15559 flip=0;
15560 tile+=12;
15561 break;
15562
15563 case r_down: //ul
15564 flip=0;
15565 tile+=20;
15566 break;
15567
15568 case down: //ur
15569 flip=0;
15570 tile+=24;
15571 break;
15572
15573 case r_up: //dl
15574 flip=0;
15575 tile+=28;
15576 break;
15577
15578 case right: //dr
15579 flip=0;
15580 tile+=32;
15581 break;
15582 }
15583
15584 tile+=f2;
15585 }
15586 else
15587 {
15588 tile+=(clk>=6)?1:0;
15589 }
15590 }
15591
15592 enemy::draw(dest);
15593 }
15594
15595 eBigDig::eBigDig(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
15596 {
15597 superman=1;
15598
15599 SIZEflags = d->SIZEflags;
15600 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
15601 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
15602 // al_trace("Enemy txsz:%i\n", txsz);
15603 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
15604 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
15605 else hxsz=32;
15606 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
15607 else hysz=32;
15608 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
15609 else hzsz=16; // hard to jump.
15610 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
15611 else hxofs=-8;
15612 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
15613 else hyofs=-8;
15614 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
15615 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
15616 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
15617 {
15618 yofs = d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
15619 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
15620 }
15621
15622 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
15623
15624
15625 }
15626
15627 bool eBigDig::animate(int32_t index)
15628 {
15629 if(switch_hooked) return enemy::animate(index);
15630 if(dying)
15631 return Dead(index);
15632
15633 if(clk==0)
15634 {
15635 removearmos(x,y);
15636 }
15637
15638 switch(misc)
15639 {
15640 case 0:
15641 variable_walk_8(rate,homing,hrate,spw_floater,-8,-16,23,23);
15642 break;
15643
15644 case 1:
15645 ++misc;
15646 break;
15647
15648 case 2:
15649 for(int32_t i=0; i<dmisc5; i++)
15650 {
15651 addenemy(x,y,dmisc1+0x1000,-15);
15652 }
15653
15654 for(int32_t i=0; i<dmisc6; i++)
15655 {
15656 addenemy(x,y,dmisc2+0x1000,-15);
15657 }
15658
15659 for(int32_t i=0; i<dmisc7; i++)
15660 {
15661 addenemy(x,y,dmisc3+0x1000,-15);
15662 }
15663
15664 for(int32_t i=0; i<dmisc8; i++)
15665 {
15666 addenemy(x,y,dmisc4+0x1000,-15);
15667 }
15668
15669 if(itemguy) // Hand down the carried item
15670 {
15671 guycarryingitem = guys.Count()-1;
15672 ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
15673 itemguy = false;
15674 }
15675
15676 stop_bgsfx(index);
15677
15678 if(deadsfx > 0) sfx(deadsfx,pan(int32_t(x)));
15679
15680 return true;
15681 }
15682
15683 return enemy::animate(index);
15684 }
15685
15686 void eBigDig::draw(BITMAP *dest)
15687 {
15688 if(anim!=aDIG)
15689 {
15690 update_enemy_frame();
15691 xofs-=8;
15692 yofs-=8;
15693 drawblock(dest,15);
15694 xofs+=8;
15695 yofs+=8;
15696 return;
15697 }
15698
15699 tile = o_tile;
15700 int32_t fdiv = frate/4;
15701 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
15702
15703 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
15704 efrate:((clk>=(frate>>1))?1:0);
15705
15706 if ( do_animation )
15707 {
15708 if(get_bit(quest_rules,qr_NEWENEMYTILES))
15709 {
15710 switch(dir-8) //directions get screwed up after 8. *shrug*
15711 {
15712 case up: //u
15713 flip=0;
15714 break;
15715
15716 case l_up: //d
15717 flip=0;
15718 tile+=8;
15719 break;
15720
15721 case l_down: //l
15722 flip=0;
15723 tile+=40;
15724 break;
15725
15726 case left: //r
15727 flip=0;
15728 tile+=48;
15729 break;
15730
15731 case r_down: //ul
15732 flip=0;
15733 tile+=80;
15734 break;
15735
15736 case down: //ur
15737 flip=0;
15738 tile+=88;
15739
15740 break;
15741
15742 case r_up: //dl
15743 flip=0;
15744 tile+=120;
15745 break;
15746
15747 case right: //dr
15748 flip=0;
15749 tile+=128;
15750 break;
15751 }
15752
15753 tile+=(f2*2);
15754 }
15755 else
15756 {
15757 tile+=(f2)?0:2;
15758 flip=(clk&1)?1:0;
15759 }
15760 }
15761
15762 xofs-=8;
15763 yofs-=8;
15764 drawblock(dest,15);
15765 xofs+=8;
15766 yofs+=8;
15767 }
15768
15769 int32_t eBigDig::takehit(weapon *w)
15770 {
15771 int32_t wpnId = w->id;
15772
15773 if(wpnId==wWhistle && misc==0)
15774 misc=1;
15775
15776 return 0;
15777 }
15778
15779 /*
15780 eGanon::eGanon(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
15781 {
15782 hxofs=hyofs=8;
15783 hzsz=16; //can't be jumped.
15784 clk2=70;
15785 misc=-1;
15786 mainguy=!getmapflag();
15787 }
15788
15789 bool eGanon::animate(int32_t index)
15790 {
15791 if(switch_hooked) return enemy::animate(index);
15792 if(dying)
15793
15794 return Dead(index);
15795
15796 if(clk==0)
15797 {
15798 removearmos(x,y);
15799 }
15800
15801 switch(misc)
15802 {
15803 case -1:
15804 misc=0;
15805
15806 case 0:
15807 if(++clk2>72 && !(zc_oldrand()&3))
15808 {
15809 addEwpn(x,y,z,wpn,3,wdp,dir,getUID());
15810 sfx(wpnsfx(wpn),pan(int32_t(x)));
15811 clk2=0;
15812 }
15813
15814 Stunclk=0;
15815 constant_walk(rate,homing,spw_none);
15816 break;
15817
15818 case 1:
15819 case 2:
15820 if(--Stunclk<=0)
15821 {
15822 int32_t r=zc_oldrand();
15823
15824 if(r&1)
15825 {
15826 y=96;
15827
15828 if(r&2)
15829 x=160;
15830 else
15831 x=48;
15832
15833 if(tooclose(x,y,48))
15834 x=208-x;
15835 }
15836
15837 //if ( editorflags & ENEMY_FLAG15 && current_item_id(itype_amulet,false) >= 2 ) //visible to Amulet 2
15838 //{
15839 // loadpalset(9,pSprite(spBROWN)); //make Ganon visible?
15840 // }
15841 // else
15842 // {
15843 loadpalset(csBOSS,pSprite(d->bosspal));
15844 // }
15845 misc=0;
15846 }
15847
15848 break;
15849
15850 case 3:
15851 {
15852 if(hclk>0)
15853 break;
15854
15855 misc=4;
15856 clk=0;
15857 hxofs=1000;
15858 loadpalset(9,pSprite(spPILE));
15859 music_stop();
15860 stop_sfx(WAV_ROAR);
15861
15862 if(deadsfx>0) sfx(deadsfx,pan(int32_t(x)));
15863
15864 sfx(WAV_GANON);
15865 //Ganon's dustpile; fall in sideview. -Z
15866 item *dustpile = new item(x+8,y+8,(zfix)0,iPile,ipDUMMY,0);
15867 dustpile->linked_parent = eeGANON;
15868 setmapflag();
15869 //items.add(new item(x+8,y+8,(zfix)0,iPile,ipDUMMY,0));
15870 break;
15871 }
15872
15873 case 4:
15874 if(clk>=80)
15875 {
15876 misc=5;
15877
15878 if(getmapflag())
15879 {
15880 game->lvlitems[dlevel]|=liBOSS;
15881 //play_DmapMusic();
15882 playLevelMusic();
15883 return true;
15884 }
15885
15886 sfx(WAV_CLEARED);
15887 items.add(new item(x+8,y+8,(zfix)0,iBigTri,ipBIGTRI,0));
15888 setmapflag();
15889 }
15890
15891 break;
15892 }
15893
15894 //if ( editorflags & ENEMY_FLAG15 ) //visible to Amulet 2
15895 //{
15896 //if ( current_item_id(itype_amulet,false) >= 2 )
15897 //{
15898 /// loadpalset(9,pSprite(spBROWN)); //make Ganon visible?
15899 //}
15900 //}
15901
15902
15903 return enemy::animate(index);
15904 }
15905
15906
15907 int32_t eGanon::takehit(weapon *w)
15908 {
15909 //these are here to bypass compiler warnings about unused arguments
15910 int32_t wpnId = w->id;
15911 int32_t power = w->power;
15912 int32_t enemyHitWeapon = w->parentitem;
15913
15914 switch(misc)
15915 {
15916 case 0:
15917 {
15918 //if we're not using the editor defences, and Ganon isn't hit by a sword, return.
15919 if(wpnId!=wSword && !(editorflags & ENEMY_FLAG14))
15920 return 0;
15921
15922 //if we are not using the new defences, just reduce his HP
15923 if (!(editorflags & ENEMY_FLAG14))
15924 {
15925 hp-=power;
15926 if(hp>0)
15927 {
15928 misc=1;
15929 Stunclk=64;
15930 }
15931 else
15932 {
15933 loadpalset(csBOSS,pSprite(spBROWN));
15934 misc=2;
15935 Stunclk=284;
15936 hp=guysbuf[id&0xFFF].hp; //16*game->get_hero_dmgmult();
15937 }
15938
15939 sfx(WAV_EHIT,pan(int32_t(x)));
15940
15941 if(hitsfx>0) sfx(hitsfx,pan(int32_t(x)));
15942
15943 return 1;
15944 }
15945 //otherwise, resolve his defence.
15946 else
15947 {
15948 int32_t def = enemy::takehit(w); //This works, but it instantly kills him if it does enough damage.
15949 if(hp>0)
15950 {
15951 misc=1;
15952 Stunclk=64;
15953 }
15954 else
15955 {
15956 loadpalset(csBOSS,pSprite(spBROWN));
15957 misc=2;
15958 Stunclk=284;
15959 hp=guysbuf[id&0xFFF].hp; //16*game->get_hero_dmgmult();
15960 }
15961
15962 sfx(WAV_EHIT,pan(int32_t(x)));
15963
15964 if(hitsfx>0) sfx(hitsfx,pan(int32_t(x)));
15965
15966
15967 return 1;
15968 }
15969 }
15970 case 2:
15971 {
15972 if
15973 (
15974 ( dmisc14 > 0 && !enemyHitWeapon == dmisc14 ) //special weapon needed to kill ganon specified in editor
15975 || //or nothing specified, use silver arrows+
15976 ( dmisc14 <= 0 && (wpnId!=wArrow || (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_arrow))<4))
15977 )
15978 return 0;
15979 {
15980 misc=3;
15981 hclk=81;
15982 loadpalset(9,pSprite(spBROWN));
15983 return 1;
15984 }
15985
15986 }
15987 }
15988
15989 return 0;
15990 }
15991
15992 void eGanon::draw(BITMAP *dest)
15993 {
15994 switch(misc)
15995 {
15996 case 0:
15997 if((clk&3)==3)
15998 tile=(zc_oldrand()%5)*2+o_tile;
15999
16000 if(db!=999)
16001 break;
16002
16003 case 2:
16004 if(Stunclk<64 && (Stunclk&1) )
16005 {
16006 if
16007 (
16008 ( (editorflags & ENEMY_FLAG1) && current_item_power(itype_amulet) >= 2 && (editorflags & ENEMY_FLAG15) )
16009 ||
16010 ( (editorflags & ENEMY_FLAG2) && (game->item[dmisc13]) && (editorflags & ENEMY_FLAG15) )
16011 )
16012 {
16013 goto ganon_draw; //draw his weapons if we can see him
16014 }
16015 break;
16016 }
16017
16018 case -1:
16019 tile=o_tile;
16020
16021 //fall through
16022 case 1:
16023 case 3:
16024 ganon_draw:
16025 drawblock(dest,15);
16026 break;
16027
16028 case 4:
16029 draw_guts(dest);
16030 draw_flash(dest);
16031 break;
16032 }
16033
16034 if ( editorflags & ENEMY_FLAG1 ) //visible to Amulet 2
16035 {
16036 if
16037 (
16038 ( (editorflags & ENEMY_FLAG1) && current_item_power(itype_amulet) >= 2 && (editorflags & ENEMY_FLAG15) )
16039 ||
16040 ( (editorflags & ENEMY_FLAG2) && (game->item[dmisc13]) && (editorflags & ENEMY_FLAG15) )
16041 )
16042 {
16043 draw_guts(dest); //makes his shots visible, but not him
16044 draw_flash(dest);
16045 }
16046 }
16047 }
16048
16049 void eGanon::draw_guts(BITMAP *dest)
16050 {
16051 int32_t c = zc_min(clk>>3,8);
16052 tile = clk<24 ? 74 : 75;
16053 overtile16(dest,tile,x+8,y+c+playing_field_offset,9,0);
16054 overtile16(dest,tile,x+8,y+16-c+playing_field_offset,9,0);
16055 overtile16(dest,tile,x+c,y+8+playing_field_offset,9,0);
16056 overtile16(dest,tile,x+16-c,y+8+playing_field_offset,9,0);
16057 overtile16(dest,tile,x+c,y+c+playing_field_offset,9,0);
16058 overtile16(dest,tile,x+16-c,y+c+playing_field_offset,9,0);
16059 overtile16(dest,tile,x+c,y+16-c+playing_field_offset,9,0);
16060 overtile16(dest,tile,x+16-c,y+16-c+playing_field_offset,9,0);
16061 }
16062
16063 void eGanon::draw_flash(BITMAP *dest)
16064 {
16065
16066 int32_t c = clk-(clk>>2);
16067 cs = (frame&3)+6;
16068 overtile16(dest,194,x+8,y+8-clk+playing_field_offset,cs,0);
16069 overtile16(dest,194,x+8,y+8+clk+playing_field_offset,cs,2);
16070 overtile16(dest,195,x+8-clk,y+8+playing_field_offset,cs,0);
16071 overtile16(dest,195,x+8+clk,y+8+playing_field_offset,cs,1);
16072 overtile16(dest,196,x+8-c,y+8-c+playing_field_offset,cs,0);
16073 overtile16(dest,196,x+8+c,y+8-c+playing_field_offset,cs,1);
16074 overtile16(dest,196,x+8-c,y+8+c+playing_field_offset,cs,2);
16075 overtile16(dest,196,x+8+c,y+8+c+playing_field_offset,cs,3);
16076 }
16077 */
16078
16079 eGanon::eGanon(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
16080 {
16081 hxofs=hyofs=8;
16082 if (editorflags & ENEMY_FLAG3)
16083 {
16084 hxofs = 4;
16085 hyofs = 4;
16086 hxsz = 24;
16087 hysz = 24;
16088 SIZEflags|=guyflagOVERRIDE_HIT_WIDTH;
16089 SIZEflags|=guyflagOVERRIDE_HIT_HEIGHT;
16090 }
16091 hzsz=16; //can't be jumped.
16092 clk2=70;
16093 misc=-1;
16094 mainguy=(!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr->flags9&fBELOWRETURN));
16095 }
16096
16097 bool eGanon::animate(int32_t index) //DO NOT ADD a check for do_animation to this version of GANON!! -Z
16098 {
16099 if(dying)
16100
16101 return Dead(index);
16102
16103 if(clk==0)
16104 {
16105 removearmos(x,y);
16106 }
16107
16108 switch(misc)
16109 {
16110 case -1:
16111 misc=0;
16112 [[fallthrough]];
16113 case 0:
16114 if(++clk2>72 && !(zc_oldrand()&3))
16115 {
16116 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
16117 sfx(wpnsfx(wpn),pan(int32_t(x)));
16118 clk2=0;
16119 }
16120
16121 Stunclk=0;
16122 constant_walk(rate,homing,spw_none);
16123 break;
16124
16125 case 1:
16126 case 2:
16127 if(--Stunclk<=0)
16128 {
16129 int32_t r=zc_oldrand();
16130
16131 if(r&1)
16132 {
16133 y=96;
16134
16135 if(r&2)
16136 x=160;
16137 else
16138 x=48;
16139
16140 if(tooclose(x,y,48))
16141 x=208-x;
16142 }
16143
16144 loadpalset(csBOSS,pSprite(d->bosspal));
16145 misc=0;
16146 }
16147
16148 break;
16149
16150 case 3:
16151 {
16152 if(hclk>0)
16153 break;
16154
16155 misc=4;
16156 clk=0;
16157 hxofs=1000;
16158 loadpalset(9,pSprite(spPILE));
16159 music_stop();
16160 stop_sfx(WAV_ROAR);
16161
16162 if(deadsfx>0) sfx(deadsfx,pan(int32_t(x)));
16163
16164 sfx(WAV_GANON);
16165 //Ganon's dustpile; fall in sideview. -Z
16166 //item *dustpile = new item(x+8,y+8,(zfix)0,iPile,ipDUMMY,0);
16167 //dustpile->miscellaneous[31] = eeGANON;
16168 items.add(new item(x+8,y+8,(zfix)0,iPile,ipDUMMY,0));
16169 item *dustpile = NULL;
16170 //dustpile = (item *)items.spr(items.Count() - 1)->getUID();
16171 dustpile = (item *)items.spr(items.Count() - 1);
16172 dustpile->linked_parent = eeGANON; //was miscellaneous[31]
16173 //setmapflag(); //Could be why the Triforce doesn't drop. Disabling this now. -Z ( 6th March, 2019 )
16174 //items.add(new item(x+8,y+8,(zfix)0,iPile,ipDUMMY,0));
16175 break;
16176 }
16177
16178 case 4:
16179 if(clk>=80)
16180 {
16181 misc=5;
16182
16183 //game->lvlitems[dlevel]|=liBOSS;
16184
16185 sfx(WAV_CLEARED);
16186 //Add the big TF over the ashes!
16187 for(word q = 0; q < items.Count(); q++)
16188 {
16189 item *ashes = (item*)items.spr(q);
16190 if ( ashes->linked_parent == eeGANON && (ashes->pickup&ipDUMMY))
16191 {
16192 //Z_scripterrlog("Found correct dustpile!\n");
16193 items.add(new item(ashes->x,ashes->y,(zfix)0,iBigTri,ipBIGTRI,0));
16194 item *bigtriforce = NULL;
16195 bigtriforce = (item *)items.spr(items.Count() - 1);
16196 bigtriforce->linked_parent = eeGANON;
16197 }
16198 }
16199 //setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
16200 //game->lvlitems[dlevel]|=liBOSS; // if we had more rule bits, we could mark him dead so that he does not respawn. -Z
16201 }
16202
16203 break;
16204 case 5: return true;
16205 }
16206
16207 return enemy::animate(index);
16208 }
16209
16210
16211 int32_t eGanon::takehit(weapon *w)
16212 {
16213 //these are here to bypass compiler warnings about unused arguments
16214 int32_t wpnId = w->id;
16215 int32_t power = w->power;
16216 int32_t enemyHitWeapon = w->parentitem;
16217
16218 switch(misc)
16219 {
16220 case 0:
16221 if(wpnId!=wSword)
16222 return 0;
16223
16224 hp-=power;
16225
16226 if(hp>0)
16227 {
16228 misc=1;
16229 Stunclk=64;
16230 }
16231 else
16232 {
16233 loadpalset(csBOSS,pSprite(spBROWN));
16234 misc=2;
16235 Stunclk=284;
16236 hp=guysbuf[id&0xFFF].hp; //16*game->get_hero_dmgmult();
16237 }
16238
16239 sfx(WAV_EHIT,pan(int32_t(x)));
16240
16241 if(hitsfx>0) sfx(hitsfx,pan(int32_t(x)));
16242
16243 return 1;
16244
16245 case 2:
16246 if(wpnId!=wArrow || (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_arrow))<4)
16247 return 0;
16248
16249 misc=3;
16250 hclk=81;
16251 loadpalset(9,pSprite(spBROWN));
16252 return 1;
16253 }
16254
16255 return 0;
16256 }
16257
16258 void eGanon::draw(BITMAP *dest)
16259 {
16260 switch(misc)
16261 {
16262 case 0:
16263 if((clk&3)==3)
16264 tile=(zc_oldrand()%5)*2+o_tile;
16265
16266 if ( (editorflags & ENEMY_FLAG1) && current_item_power(itype_amulet) >= 2 ) //ganon is visible to level 2 amulet
16267 {
16268
16269 if ( editorflags & ENEMY_FLAG16 ) //draw cloaked
16270 {
16271 int odraw = drawstyle;
16272 drawstyle = 2;
16273 drawblock(dest,15);
16274 drawstyle = odraw;
16275 }
16276 else
16277 {
16278 drawblock(dest,15);
16279 }
16280 break;
16281
16282 }
16283 else if ( (editorflags & ENEMY_FLAG2) && (game->item[dmisc13]) )
16284 {
16285 if ( editorflags & ENEMY_FLAG16 ) //draw cloaked
16286 {
16287 int odraw = drawstyle;
16288 drawstyle = 2;
16289 drawblock(dest,15);
16290 drawstyle = odraw;
16291 }
16292 else
16293 {
16294 drawblock(dest,15);
16295 }
16296 break;
16297 }
16298 if(db!=999)
16299 break;
16300 [[fallthrough]];
16301 case 2:
16302 if(Stunclk<64 && (Stunclk&1))
16303 break;
16304 [[fallthrough]];
16305 case -1:
16306 tile=o_tile;
16307
16308 [[fallthrough]];
16309 case 1:
16310 case 3:
16311 drawblock(dest,15);
16312 break;
16313
16314 case 4:
16315 draw_guts(dest);
16316 draw_flash(dest);
16317 break;
16318 }
16319 }
16320
16321 void eGanon::draw_guts(BITMAP *dest)
16322 {
16323 int32_t c = zc_min(clk>>3,8);
16324 tile = clk<24 ? 74 : 75;
16325 overtile16(dest,tile,x+8,y+c+playing_field_offset,9,0);
16326 overtile16(dest,tile,x+8,y+16-c+playing_field_offset,9,0);
16327 overtile16(dest,tile,x+c,y+8+playing_field_offset,9,0);
16328 overtile16(dest,tile,x+16-c,y+8+playing_field_offset,9,0);
16329 overtile16(dest,tile,x+c,y+c+playing_field_offset,9,0);
16330 overtile16(dest,tile,x+16-c,y+c+playing_field_offset,9,0);
16331 overtile16(dest,tile,x+c,y+16-c+playing_field_offset,9,0);
16332 overtile16(dest,tile,x+16-c,y+16-c+playing_field_offset,9,0);
16333 }
16334
16335 void eGanon::draw_flash(BITMAP *dest)
16336 {
16337
16338 int32_t c = clk-(clk>>2);
16339 cs = (frame&3)+6;
16340 overtile16(dest,194,x+8,y+8-clk+playing_field_offset,cs,0);
16341 overtile16(dest,194,x+8,y+8+clk+playing_field_offset,cs,2);
16342 overtile16(dest,195,x+8-clk,y+8+playing_field_offset,cs,0);
16343 overtile16(dest,195,x+8+clk,y+8+playing_field_offset,cs,1);
16344 overtile16(dest,196,x+8-c,y+8-c+playing_field_offset,cs,0);
16345 overtile16(dest,196,x+8+c,y+8-c+playing_field_offset,cs,1);
16346 overtile16(dest,196,x+8-c,y+8+c+playing_field_offset,cs,2);
16347 overtile16(dest,196,x+8+c,y+8+c+playing_field_offset,cs,3);
16348 }
16349
16350 void getBigTri(int32_t id2)
16351 {
16352 /*
16353 *************************
16354 * BIG TRIFORCE SEQUENCE *
16355 *************************
16356 0 BIGTRI out, WHITE flash in
16357 4 WHITE flash out, PILE cset white
16358 8 WHITE in
16359 ...
16360 188 WHITE out
16361 191 PILE cset red
16362 200 top SHUTTER opens
16363 209 bottom SHUTTER opens
16364 */
16365 sfx(itemsbuf[id2].playsound);
16366 guys.clear();
16367
16368 if(itemsbuf[id2].flags & ITEM_GAMEDATA)
16369 {
16370 game->lvlitems[dlevel]|=liTRIFORCE;
16371 }
16372
16373 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
16374
16375 draw_screen(tmpscr);
16376
16377 for(int32_t f=0; f<24*8 && !Quit; f++)
16378 {
16379 if(f==4)
16380 {
16381 for(int32_t i=1; i<16; i++)
16382 {
16383 RAMpal[CSET(9)+i]=_RGB(63,63,63);
16384 }
16385 }
16386
16387 if((f&7)==0)
16388 {
16389 for(int32_t cs=2; cs<5; cs++)
16390 {
16391 for(int32_t i=1; i<16; i++)
16392 {
16393 RAMpal[CSET(cs)+i]=_RGB(63,63,63);
16394 }
16395 }
16396
16397 refreshpal=true;
16398 }
16399
16400 if((f&7)==4)
16401 {
16402 if(currscr<128) loadlvlpal(DMaps[currdmap].color);
16403 else loadlvlpal(0xB);
16404 }
16405
16406 if(f==191)
16407 {
16408 loadpalset(9,pSprite(spPILE));
16409 }
16410
16411 advanceframe(true);
16412 }
16413
16414 //play_DmapMusic();
16415 playLevelMusic();
16416
16417 if(itemsbuf[id2].flags & ITEM_FLAG1 && currscr < 128)
16418 {
16419 Hero.dowarp(1,0); //side warp
16420 }
16421 }
16422
16423 /**********************************/
16424 /*** Multiple-Segment Enemies ***/
16425 /**********************************/
16426
16427
16428 //! No. I am not adding SIZEflags to Moldorm and Lanmola. -Z 12 Aug 2020
16429 eMoldorm::eMoldorm(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
16430 {
16431 if( !(editorflags & ENEMY_FLAG5) )
16432 {
16433 x=128;
16434 y=48;
16435 }
16436 //else { x = X; y = Y; }
16437 dir=(zc_oldrand()&7)+8;
16438 superman=1;
16439 fading=fade_invisible;
16440 hxofs=1000;
16441 segcnt=clk;
16442 segid=Id|0x1000;
16443 clk=0;
16444 id=guys.Count();
16445 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
16446 tile=o_tile;
16447 hitdir = -1;
16448 stickclk = 0;
16449
16450 /*
16451 if (get_bit(quest_rules,qr_NEWENEMYTILES))
16452 {
16453 tile=nets+1220;
16454 }
16455 else
16456 {
16457 tile=57;
16458 }
16459 */
16460 }
16461
16462 bool eMoldorm::animate(int32_t index)
16463 {
16464 if(switch_hooked) return enemy::animate(index);
16465 int32_t max_y = isdungeon() ? 100 : 100+28; //warning: Ugly hack. -Z
16466 if ( y > (max_y) )
16467 {
16468 ++stickclk; //Keep Moldorm from pacinn the bottom row or leaving the screen via the bottom edge. -Z 8th Sept, 2019
16469 //Z_scripterrlog("Stickclk is %d\n", stickclk);
16470 }
16471 if ( stickclk > 45 )
16472 {
16473 stickclk = 0;
16474 newdir_8_old(rate,homing,spw_floater); //chage dir to keep from getting stuck.
16475 }
16476
16477
16478 if(clk==0)
16479 {
16480 removearmos(x,y);
16481 }
16482
16483 if(clk2)
16484 {
16485 if(--clk2 == 0)
16486 {
16487 if(flags&guy_neverret)
16488 never_return(index);
16489
16490 if(!dmisc2 || (editorflags & ENEMY_FLAG6))
16491 leave_item();
16492
16493 stop_bgsfx(index);
16494 return true;
16495 }
16496 }
16497 else
16498 {
16499 if(stunclk>0)
16500 stunclk=0;
16501 constant_walk_8_old(rate,homing,spw_floater);
16502
16503
16504 misc=dir;
16505
16506 // If any higher-numbered segments were killed, segcnt can be too high,
16507 // leading to a crash
16508 if(index+segcnt>=guys.Count())
16509 segcnt=guys.Count()-index-1;
16510
16511 for(int32_t i=index+1; i<index+segcnt+1; i++)
16512 {
16513 enemy* segment=((enemy*)guys.spr(i));
16514
16515 // More validation - if segcnt was wrong, this may not
16516 // actually be a Moldorm segment
16517 if(segment->id!=segid)
16518 {
16519 segcnt=i-index-1;
16520 break;
16521 }
16522
16523 if(i==index+1)
16524 {
16525 x=segment->x;
16526 y=segment->y;
16527 }
16528
16529 segment->o_tile=tile; //I refuse to fuck with adding scripttile to segmented enemies. -Z
16530 //Script your own blasted segmented bosses!! -Z
16531 segment->parent_script_UID = this->script_UID;
16532 if((i==index+segcnt)&&(i!=index+1)) //tail
16533 {
16534 segment->dummy_int[1]=2;
16535 }
16536 else
16537 {
16538 segment->dummy_int[1]=1;
16539 }
16540
16541 if(i==index+1) //head
16542 {
16543 segment->dummy_int[1]=0;
16544 }
16545
16546 if(segment->hp <= 0)
16547 {
16548 int32_t offset=1;
16549
16550 for(int32_t j=i; j<index+segcnt; j++)
16551 {
16552 // Triple-check
16553 if(((enemy*)guys.spr(j+1))->id!=segid)
16554 {
16555 segcnt=j-index+1; // Add 1 because of --segcnt below
16556 break;
16557 }
16558 zc_swap(((enemy*)guys.spr(j))->hp,((enemy*)guys.spr(j+1))->hp);
16559 zc_swap(((enemy*)guys.spr(j))->hclk,((enemy*)guys.spr(j+1))->hclk);
16560 }
16561
16562 segment->hclk=33;
16563 --segcnt;
16564 --i; // Recheck the same index in case multiple segments died at once
16565 }
16566 }
16567
16568 if(segcnt==0)
16569 {
16570 clk2=19;
16571
16572 x=guys.spr(index+1)->x;
16573 y=guys.spr(index+1)->y;
16574 }
16575 }
16576
16577 return false;
16578 }
16579
16580 esMoldorm::esMoldorm(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
16581 {
16582 if( !(editorflags & ENEMY_FLAG5) )
16583 {
16584 x=128;
16585 y=48;
16586 }
16587
16588 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
16589 hyofs=4;
16590 hxsz=hysz=8;
16591 hxofs=1000;
16592 mainguy=count_enemy=false;
16593 parentclk = 0;
16594 bgsfx=-1;
16595 flags&=~guy_neverret;
16596 //deadsfx = WAV_EDEAD;
16597 isCore = false;
16598 }
16599
16600 bool esMoldorm::animate(int32_t index)
16601 {
16602 if(switch_hooked) return enemy::animate(index);
16603 // Shouldn't be possible, but better to be sure
16604 if(index==0)
16605 dying=true;
16606
16607 if(dying)
16608 {
16609 if(!dmisc2)
16610 item_set=0;
16611
16612 return Dead(index);
16613 }
16614
16615 if(clk>=0)
16616 {
16617 hxofs=4;
16618 step=((enemy*)guys.spr(index-1))->step;
16619
16620 if(parentclk == 0)
16621 {
16622 misc=dir;
16623 dir=((enemy*)guys.spr(index-1))->misc;
16624 //do alignment, as in parent's animation :-/ -DD
16625 x.doFloor();
16626 y.doFloor();
16627 }
16628
16629 parentclk=(parentclk+1)%((int32_t)(8.0/step));
16630
16631 if(!watch)
16632 {
16633 sprite::move(step);
16634 }
16635 }
16636
16637 return enemy::animate(index);
16638 }
16639
16640 int32_t esMoldorm::takehit(weapon *w)
16641 {
16642 if(enemy::takehit(w))
16643 return (w->id==wSBomb) ? 1 : 2; // force it to wait a frame before checking sword attacks again
16644
16645 return 0;
16646 }
16647
16648 void esMoldorm::draw(BITMAP *dest)
16649 {
16650 tile=o_tile;
16651 int32_t fdiv = frate/4;
16652 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
16653
16654 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
16655 efrate:((clk>=(frate>>1))?1:0);
16656
16657 if(get_bit(quest_rules,qr_NEWENEMYTILES))
16658 {
16659 tile+=dummy_int[1]*40;
16660
16661 if(dir<8)
16662 {
16663 flip=0;
16664 tile+=4*zc_max(dir, 0); // dir is -1 if trapped
16665
16666 if(dir>3) // Skip to the next row for diagonals
16667 tile+=4;
16668 }
16669 else
16670 {
16671 switch(dir-8) //directions get screwed up after 8. *shrug*
16672 {
16673 case up: //u
16674 flip=0;
16675 break;
16676
16677 case l_up: //d
16678 flip=0;
16679 tile+=4;
16680 break;
16681
16682 case l_down: //l
16683 flip=0;
16684 tile+=8;
16685 break;
16686
16687 case left: //r
16688 flip=0;
16689 tile+=12;
16690 break;
16691
16692 case r_down: //ul
16693 flip=0;
16694 tile+=20;
16695 break;
16696
16697 case down: //ur
16698 flip=0;
16699 tile+=24;
16700 break;
16701
16702 case r_up: //dl
16703 flip=0;
16704 tile+=28;
16705 break;
16706
16707 case right: //dr
16708 flip=0;
16709 tile+=32;
16710 break;
16711 }
16712 }
16713
16714 tile+=f2;
16715 }
16716
16717 if(clk>=0)
16718 enemy::draw(dest);
16719 }
16720
16721 eLanmola::eLanmola(zfix X,zfix Y,int32_t Id,int32_t Clk) : eBaseLanmola(X,Y,Id,Clk)
16722 {
16723 if( !(editorflags & ENEMY_FLAG5) )
16724 {
16725 x=64;
16726 y=80;
16727 }
16728 //else { x = X; y = Y; }
16729 //zprint2("lanmola index is %d\n", index);
16730 //byte legaldirs = 0;
16731 int32_t incr = 16;
16732 //int32_t possiiblepos = 0;
16733 //int32_t positions[8] = {0};
16734
16735 //Don't spawn in pits.
16736 if ( m_walkflag_simple(x, y) )
16737 {
16738 //zprint2("Can't spawn here.\n");
16739 for ( ; incr < 240; incr += 16 )
16740 {
16741 //move if we spawn over a pit
16742 //check each direction
16743 if ( !m_walkflag_simple(x-incr, y) ) //legaldirs |= 0x1; //left
16744 {
16745 //zprint2("Spawn adjustment: -x (%d)\n", incr);
16746 x-=incr; break;
16747 }
16748 else if ( !m_walkflag_simple(x+incr, y) ) //legaldirs |= 0x2; //right
16749 {
16750 //zprint2("Spawn adjustment: +x (%d)\n", incr);
16751 x+=incr; break;
16752 }
16753 else if ( !m_walkflag_simple(x-incr, y-incr) ) //legaldirs |= 0x4; //left-up
16754 {
16755 //zprint2("Spawn adjustment: -x (%d), -y (%d)\n", incr, incr);
16756 x-=incr; y-=incr; break;
16757 }
16758 else if ( !m_walkflag_simple(x+incr, y-incr) ) //legaldirs |= 0x8; //right-up
16759 {
16760 //zprint2("Spawn adjustment: +x (%d), -y (%d)\n", incr, incr);
16761 x+=incr; y-=incr; break;
16762 }
16763 else if ( !m_walkflag_simple(x, y-incr) ) // legaldirs |= 0x10; //up
16764 {
16765 //zprint2("Spawn adjustment: -y (%d)\n", incr);
16766 y -= incr; break;
16767 }
16768 else if ( !m_walkflag_simple(x, y+incr) ) //legaldirs |= 0x20; //down
16769 {
16770 //zprint2("Spawn adjustment: +y (%d)\n", incr);
16771 y+=incr; break;
16772 }
16773 else if ( !m_walkflag_simple(x-incr, y+incr) ) //legaldirs |= 0x40; //left-down
16774 {
16775 //zprint2("Spawn adjustment: -x (%d), +y (%d)\n", incr, incr);
16776 x-=incr; y+=incr; break;
16777 }
16778 else if ( !m_walkflag_simple(x+incr, y+incr) ) //legaldirs |= 0x80; //right-down
16779 {
16780 //zprint2("Spawn adjustment: +x (%d), +y (%d)\n", incr, incr);
16781 x+=incr; y+=incr; break;
16782 }
16783 else continue;
16784
16785 }
16786
16787 }
16788
16789 dir=up;
16790 superman=1;
16791 fading=fade_invisible;
16792 hxofs=1000;
16793 segcnt=clk;
16794 clk=0;
16795 //set up move history
16796 for(int32_t i=0; i <= (1<<dmisc2); i++)
16797 prevState.push_back(std::pair<std::pair<zfix, zfix>, int32_t>(std::pair<zfix,zfix>(x,y), dir));
16798 }
16799
16800 bool eLanmola::animate(int32_t index)
16801 {
16802 if(switch_hooked) return enemy::animate(index);
16803 if(clk==0)
16804 {
16805 removearmos(x,y);
16806 }
16807
16808 if(clk2)
16809 {
16810 if(--clk2 == 0)
16811 {
16812 if(!dmisc3) //This checks if "segments drop items" isn't true, because if they don't drop items, then only killing the whole thing drops an item.
16813 leave_item();
16814
16815 stop_bgsfx(index);
16816 return true;
16817 }
16818
16819 return false;
16820 }
16821
16822
16823 //this animation style plays ALL KINDS of havoc on the Lanmola segments, since it causes
16824 //the direction AND x,y position of the lanmola to vary in uncertain ways.
16825 //I've added a complete movement history to this enemy to compensate -DD
16826 constant_walk(rate,homing,spw_none);
16827 prevState.pop_front();
16828 prevState.push_front(std::pair<std::pair<zfix, zfix>, int32_t>(std::pair<zfix, zfix>(x,y), dir));
16829
16830 // This could cause a crash with Moldorms. I didn't see the same problem
16831 // with Lanmolas, but it looks like it ought to be possible, so here's
16832 // the same solution. - Saf
16833 if(index+segcnt>=guys.Count())
16834 segcnt=guys.Count()-index-1;
16835
16836 for(int32_t i=index+1; i<index+segcnt+1; i++)
16837 {
16838 enemy* segment=((enemy*)guys.spr(i));
16839
16840 // More validation in case segcnt is wrong
16841 if((segment->id&0xFFF)!=(id&0xFFF))
16842 {
16843 segcnt=i-index-1;
16844 break;
16845 }
16846
16847 segment->o_tile=o_tile;
16848 segment->parent_script_UID = this->script_UID;
16849 if((i==index+segcnt)&&(i!=index+1))
16850 {
16851 segment->dummy_int[1]=1; //tail
16852 }
16853 else
16854 {
16855 segment->dummy_int[1]=0;
16856 }
16857
16858 if(segment->hp <= 0)
16859 {
16860 for(int32_t j=i; j<index+segcnt; j++)
16861 {
16862 // Triple-check
16863 if((((enemy*)guys.spr(j+1))->id&0xFFF)!=(id&0xFFF))
16864 {
16865 segcnt=j-index+1; // Add 1 because of --segcnt below
16866 break;
16867 }
16868 zc_swap(((enemy*)guys.spr(j))->hp,((enemy*)guys.spr(j+1))->hp);
16869 zc_swap(((enemy*)guys.spr(j))->hclk,((enemy*)guys.spr(j+1))->hclk);
16870 }
16871
16872 ((enemy*)guys.spr(i))->hclk=33;
16873 --segcnt;
16874 --i; // Recheck the same index in case multiple segments died at once
16875 }
16876 }
16877
16878 if(segcnt==0)
16879 {
16880 clk2=19;
16881 x=guys.spr(index+1)->x;
16882 y=guys.spr(index+1)->y;
16883 setmapflag(mTMPNORET);
16884 }
16885
16886 //this enemy is invincible.. BUT scripts don't know that, and can "kill" it by setting the hp negative.
16887 //which is... disastrous.
16888 hp = 1;
16889 return enemy::animate(index);
16890 }
16891
16892 esLanmola::esLanmola(zfix X,zfix Y,int32_t Id,int32_t Clk) : eBaseLanmola(X,Y,Id,Clk)
16893 {
16894 if( !(editorflags & ENEMY_FLAG5) )
16895 {
16896 x=64;
16897 y=80;
16898 }
16899 int32_t incr = 16;
16900 //Don't spawn in pits.
16901 if ( m_walkflag_simple(x, y) )
16902 {
16903 //zprint2("Can't spawn here.\n");
16904 for ( ; incr < 240; incr += 16 )
16905 {
16906 //move if we spawn over a pit
16907 //check each direction
16908 if ( !m_walkflag_simple(x-incr, y) ) //legaldirs |= 0x1; //left
16909 {
16910 //zprint2("Spawn adjustment: -x (%d)\n", incr);
16911 x-=incr; break;
16912 }
16913 else if ( !m_walkflag_simple(x+incr, y) ) //legaldirs |= 0x2; //right
16914 {
16915 //zprint2("Spawn adjustment: +x (%d)\n", incr);
16916 x+=incr; break;
16917 }
16918 else if ( !m_walkflag_simple(x-incr, y-incr) ) //legaldirs |= 0x4; //left-up
16919 {
16920 //zprint2("Spawn adjustment: -x (%d), -y (%d)\n", incr, incr);
16921 x-=incr; y-=incr; break;
16922 }
16923 else if ( !m_walkflag_simple(x+incr, y-incr) ) //legaldirs |= 0x8; //right-up
16924 {
16925 //zprint2("Spawn adjustment: +x (%d), -y (%d)\n", incr, incr);
16926 x+=incr; y-=incr; break;
16927 }
16928 else if ( !m_walkflag_simple(x, y-incr) ) // legaldirs |= 0x10; //up
16929 {
16930 //zprint2("Spawn adjustment: -y (%d)\n", incr);
16931 y -= incr; break;
16932 }
16933 else if ( !m_walkflag_simple(x, y+incr) ) //legaldirs |= 0x20; //down
16934 {
16935 //zprint2("Spawn adjustment: +y (%d)\n", incr);
16936 y+=incr; break;
16937 }
16938 else if ( !m_walkflag_simple(x-incr, y+incr) ) //legaldirs |= 0x40; //left-down
16939 {
16940 //zprint2("Spawn adjustment: -x (%d), +y (%d)\n", incr, incr);
16941 x-=incr; y+=incr; break;
16942 }
16943 else if ( !m_walkflag_simple(x+incr, y+incr) ) //legaldirs |= 0x80; //right-down
16944 {
16945 //zprint2("Spawn adjustment: +x (%d), +y (%d)\n", incr, incr);
16946 x+=incr; y+=incr; break;
16947 }
16948 else continue;
16949
16950 }
16951
16952 }
16953
16954 hxofs=1000;
16955 hxsz=8;
16956 mainguy=false;
16957 count_enemy=(id<0x2000)?true:false;
16958
16959 //set up move history
16960 for(int32_t i=0; i <= (1<<dmisc2); i++)
16961 prevState.push_back(std::pair<std::pair<zfix, zfix>, int32_t>(std::pair<zfix,zfix>(x,y), dir));
16962
16963 bgsfx = -1;
16964 isCore = false;
16965 flags&=~guy_neverret;
16966 }
16967
16968 bool esLanmola::animate(int32_t index)
16969 {
16970 if(switch_hooked) return enemy::animate(index);
16971 // Shouldn't be possible, but who knows
16972 if(index==0)
16973 dying=true;
16974
16975 if(dying)
16976 {
16977 xofs=0;
16978
16979 if(!dmisc3)
16980 item_set=0;
16981
16982 return Dead(index);
16983 }
16984
16985 if(clk>=0)
16986 {
16987 hxofs=4;
16988
16989 if(!watch)
16990 {
16991 std::pair<std::pair<zfix, zfix>, int32_t> newstate = ((eBaseLanmola*)guys.spr(index-1))->prevState.front();
16992 prevState.pop_front();
16993 prevState.push_back(newstate);
16994 x = newstate.first.first;
16995 y = newstate.first.second;
16996 dir = newstate.second;
16997 }
16998 }
16999
17000 return enemy::animate(index);
17001 }
17002
17003 int32_t esLanmola::takehit(weapon *w)
17004 {
17005 if(enemy::takehit(w))
17006 return (w->id==wSBomb) ? 1 : 2; // force it to wait a frame before checking sword attacks again
17007
17008 return 0;
17009 }
17010
17011 void esLanmola::draw(BITMAP *dest)
17012 {
17013 tile=o_tile;
17014 int32_t fdiv = frate/4;
17015 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
17016
17017 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
17018 efrate:((clk>=(frate>>1))?1:0);
17019
17020 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17021 {
17022 if(id>=0x2000)
17023 {
17024 tile+=20;
17025
17026 if(dummy_int[1]==1)
17027 {
17028 tile+=20;
17029 }
17030 }
17031
17032 switch(dir)
17033 {
17034 case up:
17035 flip=0;
17036 break;
17037
17038 case down:
17039 flip=0;
17040 tile+=4;
17041 break;
17042
17043 case left:
17044 flip=0;
17045 tile+=8;
17046 break;
17047
17048 case right:
17049 flip=0;
17050 tile+=12;
17051 break;
17052 }
17053
17054 tile+=f2;
17055 }
17056 else
17057 {
17058 if(id>=0x2000)
17059 {
17060 tile+=1;
17061 }
17062 }
17063
17064 if(clk>=0)
17065 enemy::draw(dest);
17066 }
17067
17068 eManhandla::eManhandla(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,0)
17069 {
17070 //these are here to bypass compiler warnings about unused arguments
17071 Clk=Clk;
17072 superman=1;
17073 dir=(zc_oldrand()&7)+8;
17074 armcnt=dmisc2?8:4;//((id==eMANHAN)?4:8);
17075
17076 for(int32_t i=0; i<armcnt; i++)
17077 arm[i]=i;
17078
17079 fading=fade_blue_poof;
17080 //nets+4680;
17081 adjusted=false;
17082 SIZEflags = d->SIZEflags; //Probably will be buggy. -Z 12 AUG 2020
17083 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
17084 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
17085 // al_trace("Enemy txsz:%i\n", txsz);
17086 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
17087 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
17088 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
17089 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
17090 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
17091 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
17092 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
17093 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
17094 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
17095 {
17096 yofs = d->yofs+(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
17097 }
17098
17099 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
17100 }
17101
17102 bool eManhandla::animate(int32_t index)
17103 {
17104 if(switch_hooked) return enemy::animate(index);
17105 if(dying)
17106 return Dead(index);
17107
17108 if(clk==0)
17109 {
17110 removearmos(x,y);
17111 }
17112
17113
17114 // check arm status, move dead ones to end of group
17115 for(int32_t i=0; i<armcnt; i++)
17116 {
17117 enemy* cur_arm = ((enemy*)guys.spr(index+i+1));
17118 if(!cur_arm || cur_arm->dying)
17119 {
17120 for(int32_t j=i; j<armcnt-1; j++)
17121 {
17122 zc_swap(arm[j],arm[j+1]);
17123 guys.swap(index+j+1,index+j+2);
17124 }
17125 if((editorflags & ENEMY_FLAG6)) //They only did this in 2.10
17126 {
17127 leave_item();
17128 }
17129 --armcnt;
17130 --i;
17131 continue;
17132 }
17133 if(!adjusted)
17134 {
17135 if(!dmisc2)
17136 {
17137 cur_arm->o_tile=o_tile+40;
17138 cur_arm->parent_script_UID = this->script_UID;
17139 }
17140 else
17141 {
17142 cur_arm->o_tile=o_tile+160;
17143 cur_arm->parent_script_UID = this->script_UID;
17144 }
17145 }
17146 }
17147
17148 adjusted=true;
17149
17150 // move or die
17151 if(armcnt==0)
17152 hp=0;
17153 else
17154 {
17155 // Speed starts at 0.5, and increases by 0.5 for each head lost. Max speed is 4.5.
17156 step=zc_min(zfix(4.5),(((!dmisc2)?4:8)-int64_t(armcnt))*0.5+zslongToFix(dstep*100));
17157 int32_t dx1=0, dy1=-8, dx2=15, dy2=15;
17158
17159 if(!dmisc2)
17160 {
17161 for(int32_t i=0; i<armcnt; i++)
17162 {
17163 switch(arm[i])
17164 {
17165 case 0:
17166 dy1=-24;
17167 break;
17168
17169 case 1:
17170 dy2=31;
17171 break;
17172
17173 case 2:
17174 dx1=-16;
17175 break;
17176
17177 case 3:
17178 dx2=31;
17179 break;
17180 }
17181 }
17182 }
17183 else
17184 {
17185 dx1=-8, dy1=-16, dx2=23, dy2=23;
17186
17187 for(int32_t i=0; i<armcnt; i++)
17188 {
17189 switch(arm[i]&3)
17190 {
17191 case 0:
17192 dy1=-32;
17193 break;
17194
17195 case 1:
17196 dy2=39;
17197 break;
17198
17199 case 2:
17200 dx1=-24;
17201 break;
17202
17203 case 3:
17204 dx2=39;
17205 break;
17206 }
17207 }
17208 }
17209
17210 variable_walk_8(rate,homing,hrate,spw_floater,dx1,dy1,dx2,dy2);
17211
17212 for(int32_t i=0; i<armcnt; i++)
17213 {
17214 zfix dx=(zfix)0,dy=(zfix)0;
17215
17216 if(!dmisc2)
17217 {
17218 switch(arm[i])
17219 {
17220 case 0:
17221 dy=-16;
17222 break;
17223
17224 case 1:
17225 dy=16;
17226 break;
17227
17228 case 2:
17229 dx=-16;
17230 break;
17231
17232 case 3:
17233 dx=16;
17234 break;
17235 }
17236 }
17237 else
17238 {
17239 switch(arm[i])
17240 {
17241 case 0:
17242 dy=-24;
17243 dx=-8;
17244 break;
17245
17246 case 1:
17247 dy=24;
17248 dx=8;
17249 break;
17250
17251 case 2:
17252 dx=-24;
17253 dy=8;
17254 break;
17255
17256 case 3:
17257 dx=24;
17258 dy=-8;
17259 break;
17260
17261 case 4:
17262 dy=-24;
17263 dx=8;
17264 break;
17265
17266 case 5:
17267 dy=24;
17268 dx=-8;
17269 break;
17270
17271 case 6:
17272 dx=-24;
17273 dy=-8;
17274 break;
17275
17276 case 7:
17277 dx=24;
17278 dy=8;
17279 break;
17280 }
17281 }
17282
17283 guys.spr(index+i+1)->x = x+dx;
17284 guys.spr(index+i+1)->y = y+dy;
17285 }
17286 }
17287
17288 return enemy::animate(index);
17289 }
17290
17291
17292 int32_t eManhandla::takehit(weapon *w)
17293 {
17294 int32_t wpnId = w->id;
17295
17296 if(dying)
17297 return 0;
17298
17299 switch(wpnId)
17300 {
17301 case wBomb:
17302 case wSBomb:
17303 case wSword:
17304 case wHammer:
17305 case wWand:
17306 if (get_bit(quest_rules, qr_MANHANDLA_BLOCK_SFX)) sfx(WAV_EHIT,pan(int32_t(x)));
17307
17308 case wLitBomb:
17309 case wLitSBomb:
17310 case wBait:
17311 case wWhistle:
17312 case wFire:
17313 case wWind:
17314 case wSSparkle:
17315 case wFSparkle:
17316 case wPhantom:
17317 return 0;
17318
17319 case wHookshot:
17320 case wBrang:
17321 sfx(WAV_CHINK,pan(int32_t(x)));
17322 break;
17323
17324 default:
17325 if (get_bit(quest_rules, qr_MANHANDLA_BLOCK_SFX)) sfx(WAV_EHIT,pan(int32_t(x)));
17326 else sfx(WAV_CHINK,pan(int32_t(x)));
17327
17328 }
17329
17330 return 1;
17331 }
17332
17333 void eManhandla::draw(BITMAP *dest)
17334 {
17335 tile=o_tile;
17336 int32_t fdiv = frate/4;
17337 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
17338
17339 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
17340 efrate:((clk>=(frate>>1))?1:0);
17341
17342 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17343 {
17344 if(!dmisc2)
17345 {
17346 switch(dir-8) //directions get screwed up after 8. *shrug*
17347 {
17348 case up: //u
17349 flip=0;
17350 break;
17351
17352 case l_up: //d
17353 flip=0;
17354 tile+=4;
17355 break;
17356
17357 case l_down: //l
17358 flip=0;
17359 tile+=8;
17360 break;
17361
17362 case left: //r
17363 flip=0;
17364 tile+=12;
17365 break;
17366
17367 case r_down: //ul
17368 flip=0;
17369 tile+=20;
17370 break;
17371
17372 case down: //ur
17373 flip=0;
17374 tile+=24;
17375 break;
17376
17377 case r_up: //dl
17378 flip=0;
17379 tile+=28;
17380 break;
17381
17382 case right: //dr
17383 flip=0;
17384 tile+=32;
17385 break;
17386 }
17387
17388 tile+=f2;
17389 enemy::draw(dest);
17390 } //manhandla 2, big body
17391 else
17392 {
17393
17394 switch(dir-8) //directions get screwed up after 8. *shrug*
17395 {
17396 case up: //u
17397 flip=0;
17398 break;
17399
17400 case l_up: //d
17401 flip=0;
17402 tile+=8;
17403 break;
17404
17405 case l_down: //l
17406 flip=0;
17407 tile+=40;
17408 break;
17409
17410 case left: //r
17411 flip=0;
17412 tile+=48;
17413 break;
17414
17415 case r_down: //ul
17416 flip=0;
17417 tile+=80;
17418 break;
17419
17420 case down: //ur
17421 flip=0;
17422 tile+=88;
17423 break;
17424
17425 case r_up: //dl
17426 flip=0;
17427 tile+=120;
17428 break;
17429
17430 case right: //dr
17431 flip=0;
17432 tile+=128;
17433 break;
17434 }
17435
17436 tile+=(f2*2);
17437 xofs-=8;
17438 yofs-=8;
17439 drawblock(dest,15);
17440 xofs+=8;
17441 yofs+=8;
17442 }
17443 }
17444 else
17445 {
17446 if(!dmisc2)
17447 {
17448 enemy::draw(dest);
17449 }
17450 else
17451 {
17452 xofs-=8;
17453 yofs-=8;
17454 enemy::draw(dest);
17455 xofs+=16;
17456 enemy::draw(dest);
17457 yofs+=16;
17458 enemy::draw(dest);
17459 xofs-=16;
17460 enemy::draw(dest);
17461 xofs+=8;
17462 yofs-=8;
17463 }
17464 }
17465 }
17466
17467 esManhandla::esManhandla(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)
17468 {
17469 id=misc=clk;
17470 dir = clk & 3;
17471 clk=0;
17472 mainguy=count_enemy=false;
17473 dummy_bool[0]=false;
17474 item_set=0;
17475 bgsfx=-1;
17476 deadsfx = WAV_EDEAD;
17477 flags &= (~guy_neverret);
17478 isCore = false;
17479 //Probably will be buggy. -Z 12 AUG 2020
17480 SIZEflags = d->SIZEflags;
17481 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
17482 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
17483 // al_trace("Enemy txsz:%i\n", txsz);
17484 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
17485 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
17486 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
17487 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
17488 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
17489 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
17490 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
17491 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = d->xofs;
17492 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
17493 {
17494 yofs = d->yofs+(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
17495 }
17496
17497 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = d->zofs;
17498 }
17499
17500 bool esManhandla::animate(int32_t index)
17501 {
17502 if(switch_hooked) return enemy::animate(index);
17503 if(dying)
17504 return Dead(index);
17505
17506 if(clk==0)
17507 {
17508 removearmos(x,y);
17509 }
17510
17511 if(--clk2<=0)
17512 {
17513 clk2=unsigned(zc_oldrand())%5+5;
17514 clk3^=1;
17515 }
17516
17517 if(!(zc_oldrand()&127))
17518 {
17519 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
17520 sfx(wpnsfx(wpn),pan(int32_t(x)));
17521 }
17522
17523 return enemy::animate(index);
17524 }
17525
17526 void esManhandla::draw(BITMAP *dest)
17527 {
17528 tile=o_tile;
17529 int32_t fdiv = frate/4;
17530 int32_t efrate = fdiv == 0 ? 0 : clk/fdiv;
17531 int32_t f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
17532 efrate:((clk>=(frate>>1))?1:0);
17533
17534 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17535 {
17536 switch(misc&3)
17537 {
17538 case up:
17539 break;
17540
17541 case down:
17542 tile+=4;
17543 break;
17544
17545 case left:
17546 tile+=8;
17547 break;
17548
17549 case right:
17550 tile+=12;
17551 break;
17552 }
17553
17554 tile+=f2;
17555 }
17556 else
17557 {
17558 switch(misc&3)
17559 {
17560 case down:
17561 flip=2;
17562
17563 [[fallthrough]];
17564 case up:
17565 tile=(clk3)?188:189;
17566 break;
17567
17568 case right:
17569 flip=1;
17570 [[fallthrough]];
17571
17572 case left:
17573 tile=(clk3)?186:187;
17574 break;
17575 }
17576 }
17577
17578 enemy::draw(dest);
17579 }
17580
17581 eGleeok::eGleeok(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk) //enemy((zfix)120,(zfix)48,Id,Clk)
17582 {
17583 if ( !(editorflags & ENEMY_FLAG5) )
17584 {
17585 x = 120;
17586 y = 48;
17587 }
17588 else
17589 {
17590 if ( !(editorflags & ENEMY_FLAG6) )
17591 {
17592 x = X; y = Y;
17593 }
17594 else
17595 {
17596 x = X+8; y = Y;
17597 }
17598 }
17599 hzsz = 32; // can't be jumped.
17600 flameclk=0;
17601 misc=clk; // total head count
17602 clk3=clk; // live head count
17603 clk=0;
17604 clk2=60; // fire ball clock
17605 // hp=(guysbuf[eGLEEOK2+(misc-2)].misc2)*(misc-1)*game->get_hero_dmgmult()+guysbuf[eGLEEOK2+(misc-2)].hp;
17606 hp=(guysbuf[id&0xFFF].misc2)*(misc-1)*game->get_hero_dmgmult()+guysbuf[id&0xFFF].hp;
17607 dir = down;
17608 hxofs=4;
17609 hxsz=8;
17610 // frate=17*4;
17611 fading=fade_blue_poof;
17612 //nets+5420;
17613 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17614 {
17615 /*
17616 necktile=o_tile+8;
17617 if (dmisc3)
17618 {
17619 necktile+=8;
17620 }
17621 */
17622 necktile=o_tile+dmisc6;
17623 }
17624 else
17625 {
17626 necktile=s_tile;
17627 }
17628 }
17629
17630 bool eGleeok::animate(int32_t index)
17631 {
17632 if(switch_hooked) return enemy::animate(index);
17633 if(dying)
17634 return Dead(index);
17635
17636 if(clk==0)
17637 {
17638 removearmos(x,y);
17639 }
17640
17641 // Check if a head was killed somehow...
17642 if(index+1+clk3>=guys.Count())
17643 clk3=guys.Count()-index-1;
17644 if(index+1+misc>=guys.Count())
17645 misc=guys.Count()-index-1;
17646
17647 //fix for the "kill all enemies" item
17648 if(hp==-1000)
17649 {
17650 for(int32_t i=0; i<clk3; ++i)
17651 {
17652 // I haven't seen this fail, but it seems like it ought to be
17653 // possible, so I'm checking for it. - Saf
17654 if((((enemy*)guys.spr(index+i+1))->id&0xFFF)!=(id&0xFFF))
17655 break;
17656 ((enemy*)guys.spr(index+i+1))->hp=1; // re-animate each head,
17657 ((enemy*)guys.spr(index+i+1))->misc = -1; // disconnect it,
17658 ((enemy*)guys.spr(index+i+1))->animate(index+i+1); // let it animate one frame,
17659 ((enemy*)guys.spr(index+i+1))->hp=-1000; // and kill it for good
17660 }
17661
17662 clk3=0;
17663
17664 for(int32_t i=0; i<misc; i++)
17665 {
17666 if((((enemy*)guys.spr(index+i+1))->id&0xFFF)!=(id&0xFFF))
17667 break;
17668 ((enemy*)guys.spr(index+i+1))->misc = -2; // give the signal to disappear
17669 }
17670 }
17671
17672 for(int32_t i=0; i<clk3; i++)
17673 {
17674 enemy *head = ((enemy*)guys.spr(index+i+1));
17675 head->dummy_int[1]=necktile;
17676 head->parent_script_UID = this->script_UID;
17677
17678 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17679 {
17680 head->dummy_int[2]=o_tile+dmisc8; //connected head tile
17681 head->dummy_int[3]=o_tile+dmisc9; //flying head tile
17682 }
17683 else
17684 {
17685 head->dummy_int[2]=necktile+1; //connected head tile
17686 head->dummy_int[3]=necktile+2; //flying head tile
17687 }
17688
17689 head->dmisc5=dmisc5; //neck segments
17690
17691 /*
17692 if (dmisc3)
17693 {
17694 head->dummy_bool[0]=true;
17695 }
17696 */
17697 if(head->hclk)
17698 {
17699 if(hclk==0)
17700 {
17701 hp -= 1000 - head->hp;
17702 hclk = 33;
17703
17704 if(hitsfx>0) sfx(hitsfx,pan(int32_t(head->x)));
17705
17706 sfx(WAV_EHIT,pan(int32_t(head->x)));
17707 }
17708
17709 head->hclk = 0;
17710 }
17711
17712 // Must be set in case of naughty ZScripts
17713 head->hp = 1000;
17714 }
17715
17716 if(hp<=(guysbuf[id&0xFFF].misc2)*(clk3-1)*game->get_hero_dmgmult())
17717 {
17718 ((enemy*)guys.spr(index+clk3))->misc = -1; // give signal to fly off
17719 hp=(guysbuf[id&0xFFF].misc2)*(--clk3)*game->get_hero_dmgmult();
17720 }
17721
17722 if(!dmisc3)
17723 {
17724 if(++clk2>72 && !(zc_oldrand()&3))
17725 {
17726 int32_t i=zc_oldrand()%misc;
17727 enemy *head = ((enemy*)guys.spr(index+i+1));
17728 addEwpn(head->x,head->y,head->z,wpn,3,wdp,dir,getUID(), 0, head->fakez);
17729 sfx(wpnsfx(wpn),pan(int32_t(x)));
17730 clk2=0;
17731 }
17732 }
17733 else
17734 {
17735 if(++clk2>100 && !(zc_oldrand()&3))
17736 {
17737 enemy *head = ((enemy*)guys.spr(zc_oldrand()%misc+index+1));
17738 head->timer=zc_oldrand()%50+50;
17739 clk2=0;
17740 }
17741 }
17742
17743 if((hp<=0 && !immortal))
17744 {
17745 for(int32_t i=0; i<misc; i++)
17746 ((enemy*)guys.spr(index+i+1))->misc = -2; // give the signal to disappear
17747
17748 if(flags&guy_neverret) never_return(index);
17749 }
17750
17751 return enemy::animate(index);
17752 }
17753
17754 int32_t eGleeok::takehit(weapon*)
17755 {
17756 return 0;
17757 }
17758
17759 void eGleeok::draw(BITMAP *dest)
17760 {
17761 tile=o_tile;
17762
17763 if(dying)
17764 {
17765 enemy::draw(dest);
17766 return;
17767 }
17768
17769 int32_t f=clk/17;
17770
17771 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17772 {
17773 // body
17774 xofs=-8;
17775 yofs=32;
17776
17777 switch(f)
17778
17779 {
17780 case 0:
17781 tile+=0;
17782 break;
17783
17784 case 1:
17785 tile+=2;
17786 break;
17787
17788 case 2:
17789 tile+=4;
17790 break;
17791
17792 default:
17793 tile+=6;
17794 break;
17795 }
17796 }
17797 else
17798 {
17799 // body
17800 xofs=-8;
17801 yofs=32;
17802
17803 switch(f)
17804 {
17805 case 0:
17806 tile+=0;
17807 break;
17808
17809 case 2:
17810 tile+=4;
17811 break;
17812
17813 default:
17814 tile+=2;
17815 break;
17816 }
17817 }
17818
17819 enemy::drawblock(dest,15);
17820 }
17821
17822 void eGleeok::draw2(BITMAP *dest)
17823 {
17824 // the neck stub
17825 tile=necktile;
17826 xofs=0;
17827 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
17828
17829 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17830 {
17831 tile+=((clk&24)>>3);
17832 }
17833
17834 if(hp > 0 && !dont_draw())
17835 {
17836 if((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))
17837 sprite::drawcloaked(dest);
17838 else
17839 sprite::draw(dest);
17840 }
17841 }
17842
17843 esGleeok::esGleeok(zfix X,zfix Y,int32_t Id,int32_t Clk, sprite * prnt) : enemy(X,Y,Id,Clk), parent(prnt)
17844 {
17845 xoffset=0;
17846 yoffset=(zfix)((dmisc5*4+2));
17847 // dummy_bool[0]=false;
17848 timer=0;
17849 /* fixing */
17850 hp=1000;
17851 step=1;
17852 item_set=0;
17853 //x=120; y=70;
17854 x = xoffset+parent->x;
17855 y = yoffset+parent->y;
17856 hxofs=4;
17857 hxsz=8;
17858 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
17859 clk2=clk; // how int32_t to wait before moving first time
17860 clk=0;
17861 mainguy=count_enemy=false;
17862 dir=zc_oldrand();
17863 clk3=((dir&2)>>1)+2; // left or right
17864 dir&=1; // up or down
17865 dmisc5=vbound(dmisc5,1,255);
17866 isCore = false;
17867 parentCore = parent->getUID();
17868 for(int32_t i=0; i<dmisc5; i++)
17869 {
17870 nxoffset[i] = 0;
17871 nyoffset[i] = 0;
17872 nx[i] = ((((i*(int32_t)x) + (dmisc5-i)*((int32_t)parent->x))) /dmisc5);
17873 ny[i] = ((((i*(int32_t)y) + (dmisc5-i)*((int32_t)parent->y))) /dmisc5);
17874 }
17875
17876 necktile=0;
17877 //TODO compatibility? -DD
17878 /*
17879 for(int32_t i=0; i<4; i++)
17880 {
17881 nx[i]=124;
17882 ny[i]=i*6+48;
17883 }*/
17884 bgsfx=-1;
17885 //no need for deadsfx
17886 }
17887
17888 bool esGleeok::animate(int32_t index)
17889 {
17890 if(switch_hooked) return enemy::animate(index);
17891 // don't call removearmos() - it's a segment.
17892
17893 dmisc5=vbound(dmisc5,1,255);
17894
17895 if(misc == 0)
17896 {
17897 x = (xoffset+parent->x);
17898 y = (yoffset+parent->y);
17899
17900 for(int32_t i=0; i<dmisc5; i++)
17901 {
17902 nx[i] = ((((i*(int32_t)x) + (dmisc5-i)*((int32_t)parent->x))) /dmisc5) + 3 + nxoffset[i];
17903 ny[i] = ((((i*(int32_t)y) + (dmisc5-i)*((int32_t)parent->y))) /dmisc5) + nyoffset[i];
17904 }
17905 }
17906
17907 // set up the head tiles
17908 // headtile=nets+5588; //5580, actually. must adjust for direction later on
17909 /*
17910 if (dummy_bool[0]) //if this is a flame gleeok
17911 {
17912 headtile+=180;
17913 }
17914 */
17915 headtile=dummy_int[2]; //5580, actually. must adjust for direction later on
17916 flyingheadtile=dummy_int[3];
17917
17918 // set up the neck tiles
17919 necktile=dummy_int[1];
17920
17921 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17922 {
17923 necktile+=((clk&24)>>3);
17924 }
17925
17926 /*
17927 else
17928 {
17929 necktile=145;
17930 }
17931 */
17932 // ?((dummy_bool[0])?(nets+4052+(16+((clk&24)>>3))):(nets+4040+(8+((clk&24)>>3)))):145)
17933
17934 switch(misc)
17935 {
17936 case 0: // live head
17937 // set up the attached head tiles
17938 tile=headtile;
17939
17940 if(get_bit(quest_rules,qr_NEWENEMYTILES))
17941 {
17942 tile+=((clk&24)>>3);
17943 /*
17944 if (dummy_bool[0]) {
17945 tile+=1561;
17946 }
17947 */
17948 }
17949
17950 /*
17951 else
17952 {
17953 tile=146;
17954 }
17955 */
17956 if(++clk2>=0 && !(clk2&3))
17957 {
17958 if(y<= (int32_t)parent->y + 8) dir=down;
17959
17960 if(y>= (int32_t)parent->y + dmisc5*8) dir = up;
17961
17962 if(y<= (int32_t)parent->y + 10 && !(zc_oldrand()&31))
17963 {
17964 dir^=1;
17965 }
17966
17967 zfix tempx = x;
17968 zfix tempy = y;
17969
17970 sprite::move(step);
17971 xoffset += (x-tempx);
17972 yoffset += (y-tempy);
17973
17974 if(clk2>=4)
17975 {
17976 clk3^=1;
17977 clk2=-4;
17978 }
17979 else
17980 {
17981 if(x <= (int32_t)parent->x-(dmisc5*6))
17982 {
17983 clk3=right;
17984 }
17985
17986 if(x >= (int32_t)parent->x+(dmisc5*6))
17987 {
17988 clk3=left;
17989 }
17990
17991 if(y <= (int32_t)parent->y+(dmisc5*6) && !(zc_oldrand()&15))
17992 {
17993 clk3^=1; // x jig
17994 }
17995 else
17996 {
17997 if(y<=(int32_t)parent->y+(dmisc5*4) && !(zc_oldrand()&31))
17998 {
17999 clk3^=1; // x switch back
18000 }
18001
18002 clk2=-4;
18003 }
18004 }
18005
18006 zc_swap(dir,clk3);
18007 tempx = x;
18008 tempy = y;
18009 sprite::move(step);
18010 xoffset += (x-tempx);
18011 yoffset += (y-tempy);
18012 zc_swap(dir,clk3);
18013
18014 for(int32_t i=1; i<dmisc5; i++)
18015 {
18016 nxoffset[i] = (zc_oldrand()%3);
18017 nyoffset[i] = (zc_oldrand()%3);
18018 }
18019 }
18020
18021 break;
18022
18023 case 1: // flying head
18024 if(clk>=0)
18025
18026 {
18027 variable_walk_8(rate,homing,hrate,spw_floater);
18028 }
18029
18030 break;
18031
18032 // the following are messages sent from the main guy...
18033 case -1: // got chopped off
18034 {
18035 misc=1;
18036 superman=1;
18037 hxofs=xofs=0;
18038 hxsz=16;
18039 cs=8;
18040 clk=-24;
18041 clk2=40;
18042 dir=(zc_oldrand()&7)+8;
18043 step=8.0/9.0;
18044 }
18045 break;
18046
18047 case -2: // the big guy is dead
18048 return true;
18049 }
18050
18051 if(timer)
18052 {
18053 if(!(timer%8))
18054 {
18055 FireBreath(true);
18056 }
18057
18058 --timer;
18059 }
18060
18061 return enemy::animate(index);
18062 }
18063
18064 int32_t esGleeok::takehit(weapon *w)
18065 {
18066 if ((editorflags & ENEMY_FLAG7) && misc == 1)
18067 {
18068 int32_t wpnId = w->id;
18069
18070 if(dying)
18071 return 0;
18072
18073 switch(wpnId)
18074 {
18075 case wLitBomb:
18076 case wLitSBomb:
18077 case wBait:
18078 case wWhistle:
18079 case wFire:
18080 case wWind:
18081 case wSSparkle:
18082 case wFSparkle:
18083 case wPhantom:
18084 return 0;
18085
18086 case wHookshot:
18087 case wBrang:
18088 case wBeam:
18089 case wArrow:
18090 case wMagic:
18091 case wBomb:
18092 case wSBomb:
18093 sfx(WAV_CHINK,pan(int32_t(x)));
18094 break;
18095 default:
18096 break;
18097 }
18098
18099 return 1;
18100 }
18101 else
18102 {
18103 int32_t ret = enemy::takehit(w);
18104
18105 if(ret==-1)
18106 return 2; // force it to wait a frame before checking sword attacks again
18107
18108 return ret;
18109 }
18110 }
18111
18112 void esGleeok::draw(BITMAP *dest)
18113 {
18114 dmisc5=vbound(dmisc5,1,255);
18115
18116 switch(misc)
18117 {
18118 case 0: //neck
18119 if(!dont_draw())
18120 {
18121 for(int32_t i=1; i<dmisc5; i++) //draw the neck
18122 {
18123 if(get_bit(quest_rules,qr_NEWENEMYTILES))
18124 {
18125 if((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))
18126 overtilecloaked16(dest,necktile+(i*dmisc7),nx[i]-4,ny[i]+playing_field_offset,0);
18127 else
18128 overtile16(dest,necktile+(i*dmisc7),nx[i]-4,ny[i]+playing_field_offset,cs,0);
18129 }
18130 else
18131 {
18132 if((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))
18133 overtilecloaked16(dest,necktile,nx[i]-4,ny[i]+playing_field_offset,0);
18134 else
18135 overtile16(dest,necktile,nx[i]-4,ny[i]+playing_field_offset,cs,0);
18136 }
18137 }
18138 }
18139
18140 break;
18141
18142 case 1: //flying head
18143 tile=flyingheadtile;
18144
18145 if(get_bit(quest_rules,qr_NEWENEMYTILES))
18146 {
18147 tile+=((clk&24)>>3);
18148 break;
18149 }
18150
18151 /*
18152 else
18153 {
18154 tile=(clk&1)?147:148;
18155 break;
18156 }
18157 */
18158 }
18159 }
18160
18161 void esGleeok::draw2(BITMAP *dest)
18162 {
18163 enemy::draw(dest);
18164 }
18165
18166 ePatra::ePatra(zfix X,zfix Y,int32_t Id,int32_t Clk) : enemy(X,Y,Id,Clk)// enemy((zfix)128,(zfix)48,Id,Clk)
18167 {
18168 if ( !(editorflags & ENEMY_FLAG5) )
18169 {
18170 x = 128;
18171 y = 48;
18172 }
18173 else { x = X; y = Y; }
18174 adjusted=false;
18175 dir=(zc_oldrand()&7)+8;
18176 //step=0.25;
18177 flycnt=dmisc1;
18178 flycnt2=dmisc2;
18179 loopcnt=0;
18180 clk4 = 0;
18181 clk5 = 0;
18182 clk6 = 0;
18183 clk7 = 0;
18184 if(dmisc6<int16_t(1))dmisc6=1; // ratio cannot be 0!
18185 SIZEflags = d->SIZEflags;
18186 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
18187 else if (dmisc10 == 1) { txsz = 2; extend = 3; }
18188 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
18189 // al_trace("Enemy txsz:%i\n", txsz);
18190 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = tysz; if ( tysz > 1 ) extend = 3; }
18191 else if (dmisc10 == 1) { tysz = 2; extend = 3; }
18192 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = hxsz;
18193 else if (dmisc10 == 1) hxsz = 32;
18194 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = hysz;
18195 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = hzsz;
18196 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = hxofs;
18197 else if (dmisc10 == 1) hxofs = -8;
18198 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = hyofs;
18199 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
18200 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)xofs;
18201 else if (dmisc10 == 1) xofs = -8;
18202 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
18203 {
18204 yofs = (int32_t)yofs; //This seems to be setting to +48 or something with any value set?! -Z
18205 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
18206 }
18207 else if (dmisc10 == 1) yofs = (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset)-8;
18208 if (editorflags & ENEMY_FLAG8) misc = 1;
18209
18210 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)zofs;
18211
18212 if (dmisc29 == 0)
18213 {
18214 if(!dmisc4)
18215 {
18216 if (dmisc10) dmisc29 = (90 / 3);
18217 else dmisc29 = (84 / 3);
18218 }
18219 else
18220 {
18221 if (dmisc10) dmisc29 = (90 / 2);
18222 else dmisc29 = (84 / 2);
18223 }
18224 }
18225 if (dmisc30 == 0)
18226 {
18227 if(!dmisc4)
18228 {
18229 if (dmisc10) dmisc30 = (90 / 3)*0.5;
18230 else dmisc30 = (84 / 3)*0.5;
18231 }
18232 else
18233 {
18234 if (dmisc10) dmisc30 = (90 / 2)*0.5;
18235 else dmisc30 = (84 / 2)*0.5;
18236 }
18237 }
18238 if (dmisc31 == 0)
18239 {
18240 if(!dmisc4)
18241 {
18242 if (dmisc10) dmisc31 = (90 / 3)*2;
18243 else dmisc31 = (84 / 3)*2;
18244 }
18245 else
18246 {
18247 if (dmisc10) dmisc31 = (90 / 2)*0.5;
18248 else dmisc31 = (84 / 2)*0.5;
18249 }
18250 }
18251 if (dmisc32 == 0)
18252 {
18253 if(!dmisc4)
18254 {
18255 if (dmisc10) dmisc32 = (90 / 3);
18256 else dmisc32 = (84 / 3);
18257 }
18258 else
18259 {
18260 if (dmisc10) dmisc32 = (90 / 2)*0.25;
18261 else dmisc32 = (84 / 2)*0.25;
18262 }
18263 }
18264 }
18265
18266 bool ePatra::animate(int32_t index)
18267 {
18268 if(switch_hooked) return enemy::animate(index);
18269 if(dying)
18270 {
18271 for(int32_t i=index+1; i<index+flycnt+flycnt2+1; i++)
18272 {
18273 ((enemy*)guys.spr(i))->hp = -1000;
18274 }
18275
18276 return Dead(index);
18277 }
18278
18279 double basesize = 84;
18280 if (dmisc10) basesize = 90;
18281 double halfsize = basesize / 2;
18282 double quartersize = halfsize / 2;
18283 double twothirdsize = (basesize / 3)*2;
18284 double onethirdsize = (basesize / 3);
18285
18286
18287 if(clk==0)
18288 {
18289 removearmos(x,y);
18290 }
18291
18292 if ((clk4 <=0 || clk4%2) && (clk7 <= 0 || clk6 <= -16))
18293 {
18294 if (!dmisc22 || loopcnt == 0 || (dmisc22 == 1 && loopcnt < 0)) variable_walk_8(rate,homing,hrate,spw_floater);
18295 if (loopcnt < 0) ++clk2;
18296 if(++clk2>basesize)
18297 {
18298 clk2=0;
18299 if ((!dmisc26 || (dmisc26 == 1 && flycnt) || (dmisc26 == 2 && !flycnt)) && (!(editorflags & ENEMY_FLAG10) || flycnt || flycnt2))
18300 {
18301 if(loopcnt > 0)
18302 --loopcnt;
18303 else if (loopcnt == 0)
18304 {
18305 if((misc%dmisc6)==0)
18306 {
18307 if (dmisc21 > 0) loopcnt=-dmisc21;
18308 else loopcnt=dmisc7;
18309 }
18310 }
18311 else if (loopcnt == -1) loopcnt=dmisc7;
18312 else ++loopcnt;
18313
18314 if (!(editorflags & ENEMY_FLAG9) || loopcnt == 0) ++misc;
18315 }
18316 else
18317 {
18318 loopcnt = 0;
18319 misc = 1;
18320 }
18321 }
18322 }
18323 if (clk4 > 0) --clk4;
18324
18325 double size=1;
18326
18327 if (clk6 < 0)
18328 {
18329 if (dmisc5 == 1 || dmisc5 == 3)
18330 {
18331 if (get_bit(quest_rules,qr_NEWENEMYTILES))
18332 {
18333 if (clk7 <= 0 || clk6 != -16) ++clk6;
18334 if (clk6 == 0) o_tile=d->e_tile;
18335 else
18336 {
18337 if (clk6 >= -16) o_tile=d->e_tile + (IsBigAnim() ? 320 : 80);
18338 else o_tile=d->e_tile + (IsBigAnim() ? 160 : 40);
18339 }
18340 }
18341 else clk6 = 0;
18342 }
18343 }
18344 else if (dmisc19) ++clk6;
18345 if (clk5 < 0) ++clk5;
18346 else if (dmisc19) ++clk5;
18347
18348 if (clk7 > 0 && clk6 >= -16) --clk7;
18349 if (clk6 > 0) clk7 = 0;
18350
18351 for(int32_t i=index+1; i<index+flycnt+1; i++)
18352 {
18353 //outside ring
18354 if(!adjusted)
18355 {
18356 if(get_bit(quest_rules,qr_NEWENEMYTILES))
18357 {
18358 ((enemy*)guys.spr(i))->o_tile=d->e_tile+dmisc8;
18359 enemy *s = ((enemy*)guys.spr(i));
18360 s->parent_script_UID = this->script_UID;
18361 }
18362 else
18363 {
18364 ((enemy*)guys.spr(i))->o_tile=o_tile+1;
18365 enemy *s = ((enemy*)guys.spr(i));
18366 s->parent_script_UID = this->script_UID;
18367 }
18368
18369 ((enemy*)guys.spr(i))->cs=dmisc9;
18370 ((enemy*)guys.spr(i))->hp=dmisc3;
18371 }
18372
18373 if(((enemy*)guys.spr(i))->hp <= 0)
18374 {
18375 for(int32_t j=i; j<index+flycnt+flycnt2; j++)
18376 {
18377 guys.swap(j,j+1);
18378 }
18379
18380 if (--flycnt == 0 && dmisc23 != 0) step += zslongToFix(dmisc23*100);
18381 }
18382 else
18383 {
18384 int32_t pos2 = ((enemy*)guys.spr(i))->misc;
18385 double a2 = (clk2-pos2*(double)basesize/(dmisc1 == 0 ? 1 : dmisc1))*PI/halfsize;
18386
18387 if(!dmisc4) //Big Ring
18388 {
18389 //maybe playing_field_offset here?
18390 if(loopcnt>0)
18391 {
18392 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*abs(dmisc31) - zc::math::Sin(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1))*((int64_t)abs(dmisc31)-abs(dmisc29));
18393 guys.spr(i)->y = -zc::math::Sin(a2+PI/2)*abs(dmisc31) + zc::math::Cos(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1))*((int64_t)abs(dmisc31)-abs(dmisc29));
18394 }
18395 else
18396 {
18397 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*abs(dmisc29);
18398 guys.spr(i)->y = -zc::math::Sin(a2+PI/2)*abs(dmisc29);
18399 }
18400
18401 temp_x=guys.spr(i)->x;
18402 temp_y=guys.spr(i)->y;
18403 }
18404 else //Oval
18405 {
18406 circle_x = zc::math::Cos(a2+PI/2)*abs(dmisc29);
18407 circle_y = -zc::math::Sin(a2+PI/2)*abs(dmisc29);
18408
18409 if(loopcnt>0)
18410 {
18411 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*abs(dmisc29);
18412 guys.spr(i)->y = (-zc::math::Sin(a2+PI/2)-zc::math::Cos(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1)))*abs(dmisc31);
18413 }
18414 else
18415 {
18416 guys.spr(i)->x = circle_x;
18417 guys.spr(i)->y = circle_y;
18418 }
18419
18420 temp_x=circle_x;
18421 temp_y=circle_y;
18422 }
18423
18424 double _MSVC2022_tmp1, _MSVC2022_tmp2;
18425 double ddir=atan2_MSVC2022_FIX(double(temp_y),double(temp_x));
18426
18427 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
18428 {
18429 guys.spr(i)->dir=l_down;
18430 }
18431 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
18432 {
18433 guys.spr(i)->dir=left;
18434 }
18435 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
18436 {
18437 guys.spr(i)->dir=l_up;
18438 }
18439 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
18440 {
18441 guys.spr(i)->dir=up;
18442 }
18443 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
18444 {
18445 guys.spr(i)->dir=r_up;
18446 }
18447 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
18448 {
18449 guys.spr(i)->dir=right;
18450 }
18451 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
18452 {
18453 guys.spr(i)->dir=r_down;
18454 }
18455 else
18456 {
18457 guys.spr(i)->dir=down;
18458 }
18459
18460 guys.spr(i)->x += x;
18461 guys.spr(i)->y += y;
18462 }
18463 }
18464
18465 if((wpn>wEnemyWeapons || (wpn >= wScript1 && wpn <= wScript10)) && (dmisc5==1 || dmisc5== 3) && (!dmisc25 || (dmisc25 == 1 && !flycnt && !flycnt2) || (dmisc25 == 2 && (flycnt || flycnt2)) || (dmisc25 == 3 && flycnt2 && !flycnt)))
18466 {
18467 int timeneeded = 48;
18468 int patbreath = (zc_oldrand()%50+50);
18469 if ((patbreath % 4) == 0) ++patbreath;
18470 if (dmisc28 == patratBREATH)
18471 {
18472 timeneeded = 48 + patbreath;
18473 }
18474 if (dmisc28 == patratSTREAM)
18475 {
18476 timeneeded = 48 + 96;
18477 }
18478 if (((((dmisc18 > 0 || ((editorflags & ENEMY_FLAG10) && !flycnt && !flycnt2)) && !(zc_oldrand() % zc_max(dmisc18, 1))) || //New 1/N chance
18479 (dmisc18 == 0 && !(zc_oldrand()&127)) //Old hardcoded firing chance
18480 || (dmisc18 == -1 && loopcnt > 0 && (clk2 == round(halfsize) && (!(editorflags & ENEMY_FLAG3) || !get_bit(quest_rules,qr_NEWENEMYTILES))
18481 || (clk4 == 10 && (editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES)))))
18482 && (clk6 >= 0) //if not in the middle of firing...
18483 && clk6 >= dmisc19) //if over the set cooldown between shots...
18484 && ((!(editorflags & ENEMY_FLAG7) || (loopcnt == 0 && (basesize*((int64_t)dmisc6 - (misc%dmisc6))) > timeneeded)) || dmisc18 == -1)) //And lastly, if not in danger of starting a loop during the attack.
18485 {
18486 switch(dmisc28)
18487 {
18488 case patratSTREAM:
18489 {
18490 clk7 = 97;
18491 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES)) clk6 = -48;
18492 else clk6 = 0;
18493 break;
18494 }
18495 case patratBREATH:
18496 {
18497 clk7 = patbreath;
18498 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES)) clk6 = -48;
18499 else clk6 = 0;
18500 break;
18501 }
18502 default:
18503 {
18504 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES))
18505 {
18506 clk6 = -48;
18507 if (editorflags & ENEMY_FLAG6) clk4 = abs(clk6) + 16;
18508 }
18509 else
18510 {
18511 clk6 = 0;
18512 if (editorflags & ENEMY_FLAG6) clk4 = 16;
18513 FirePatraWeapon();
18514 }
18515 break;
18516 }
18517 } //ew->setAngle(atan2(double(HeroY()-y),double(HeroX()-x)));
18518 }
18519 if (clk6 < 0)
18520 {
18521 switch(dmisc28)
18522 {
18523 case patratSTREAM:
18524 {
18525 if (clk7 > 0 && (clk7 % 12) == 0) FirePatraWeapon();
18526 if (editorflags & ENEMY_FLAG6) clk4 = abs(clk6) + 16;
18527 break;
18528 }
18529 case patratBREATH:
18530 {
18531 if (clk7 > 0 && (clk7 % 4) == 0) FirePatraWeapon();
18532 if (editorflags & ENEMY_FLAG6) clk4 = abs(clk6) + 16;
18533 break;
18534 }
18535 default:
18536 {
18537 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES) && clk6 == -16)
18538 {
18539 FirePatraWeapon();
18540 if (editorflags & ENEMY_FLAG6) clk4 = abs(clk6) + 16;
18541 }
18542 break;
18543 }
18544 }
18545 }
18546 }
18547
18548 size=.5;
18549 int randattempts = 0;
18550 int randeye = 0;
18551 if (flycnt2 > 0)
18552 {
18553 do
18554 {
18555 randeye = ((flycnt2 > 0) ? (zc_oldrand() % zc_max(1, flycnt2)) : 0);
18556 randeye += (index + flycnt + 1);
18557 ++randattempts;
18558 } while (((esPatra*)guys.spr(randeye))->clk5 < 0 && randattempts < 10);
18559 }
18560 bool dofire = false;
18561 if (dmisc20)
18562 {
18563 if ((dmisc18 > 0 && !(zc_oldrand() % zc_max(dmisc18, 1))) ||
18564 (dmisc18 == 0 && !(zc_oldrand()&127)) ||
18565 (dmisc18 == -1 && (loopcnt > 0 || dmisc20 == 4) && ((clk2 == round(halfsize) && (!(editorflags & ENEMY_FLAG3) || !get_bit(quest_rules,qr_NEWENEMYTILES)) && dmisc20 != 2 && dmisc20 != 4)
18566 || (clk2 == 10 && dmisc20 != 4 && ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES) || dmisc20 == 2))
18567 || ((((((misc%dmisc6) == 0 && (loopcnt == 0 && !dmisc21)) || loopcnt > 1 || loopcnt == -1) && clk2 <= 53 && clk2 >= 51 && (editorflags & ENEMY_FLAG3)) || (!(editorflags & ENEMY_FLAG3) && loopcnt > 0 && clk2 == 1)) && dmisc20 == 4))))
18568 {
18569 if (clk5 >= 0 || !(editorflags & ENEMY_FLAG3) || !get_bit(quest_rules,qr_NEWENEMYTILES))
18570 {
18571 if (clk5 >= dmisc19)
18572 {
18573 if ((!(editorflags & ENEMY_FLAG7) || (loopcnt == 0 &&
18574 (dmisc20 == 2 && (basesize*((int64_t)dmisc6 - (misc%dmisc6))) > ((int64_t)48 + (int64_t(12)*flycnt2))) ||
18575 (dmisc20 == 4 && (basesize*((int64_t)dmisc6 - (misc%dmisc6))) > ((int64_t)48 + 96)) ||
18576 (dmisc20 != 2 && dmisc20 != 4 && (basesize*((int64_t)dmisc6 - (misc%dmisc6))) > 48)))
18577 || dmisc18 == -1)
18578 dofire = true;
18579 }
18580 }
18581 }
18582 }
18583 if(flycnt2)
18584 {
18585 for(int32_t i=index+flycnt+1; i<index+flycnt+flycnt2+1; i++)//inner ring
18586 {
18587 if(!adjusted)
18588 {
18589 ((enemy*)guys.spr(i))->hp=12*game->get_hero_dmgmult();
18590
18591 if(get_bit(quest_rules,qr_NEWENEMYTILES))
18592 {
18593 if (get_bit(quest_rules,qr_PATRAS_USE_HARDCODED_OFFSETS))
18594 {
18595 switch(dmisc5)
18596 {
18597 // Center eye shoots projectiles; make room for its firing tiles
18598 case 1:
18599 case 3:
18600 ((enemy*)guys.spr(i))->o_tile=d->e_tile+120;
18601 break;
18602
18603 // Center eyes does not shoot; use tiles two rows below for inner eyes.
18604 default:
18605 case 2:
18606 ((enemy*)guys.spr(i))->o_tile=d->e_tile+40;
18607 break;
18608 }
18609 }
18610 else ((enemy*)guys.spr(i))->o_tile = d->s_tile;
18611 }
18612 else
18613 {
18614 ((enemy*)guys.spr(i))->o_tile=o_tile+1;
18615 }
18616
18617 ((enemy*)guys.spr(i))->cs=dmisc9;
18618 if (dmisc27) ((enemy*)guys.spr(i))->hp=dmisc27;
18619 }
18620
18621 if(flycnt>0)
18622 {
18623 ((enemy*)guys.spr(i))->superman=true;
18624 }
18625 else
18626 {
18627 ((enemy*)guys.spr(i))->superman=false;
18628 }
18629
18630 if(((enemy*)guys.spr(i))->hp <= 0)
18631 {
18632 for(int32_t j=i; j<index+flycnt+flycnt2; j++)
18633 {
18634 guys.swap(j,j+1);
18635 }
18636
18637 if (--flycnt2 == 0 && dmisc24 != 0) step += zslongToFix(dmisc24*100);
18638 }
18639 else
18640 {
18641 int32_t pos2 = ((enemy*)guys.spr(i))->misc;
18642 double a2 = ((clk2-pos2*basesize/(dmisc2==0 ? 1 : dmisc2))*PI/(halfsize));
18643
18644 if(dmisc4==0)
18645 {
18646 if(loopcnt>0)
18647 {
18648 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*abs(dmisc32) - zc::math::Sin(pos2*PI*2/(dmisc2==0?1:dmisc2))*((int64_t)abs(dmisc32)-abs(dmisc30));
18649 guys.spr(i)->y = -zc::math::Sin(a2+PI/2)*abs(dmisc32) + zc::math::Cos(pos2*PI*2/(dmisc2==0?1:dmisc2))*((int64_t)abs(dmisc32)-abs(dmisc30));
18650 }
18651 else
18652 {
18653 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*abs(dmisc30);
18654 guys.spr(i)->y = -zc::math::Sin(a2+PI/2)*abs(dmisc30);
18655 }
18656
18657 temp_x=guys.spr(i)->x;
18658 temp_y=guys.spr(i)->y;
18659 }
18660 else
18661 {
18662 circle_x = zc::math::Cos(a2+PI/2)*abs(dmisc30);
18663 circle_y = -zc::math::Sin(a2+PI/2)*abs(dmisc30);
18664
18665 if(loopcnt>0)
18666 {
18667 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*abs(dmisc30);
18668 guys.spr(i)->y = (-zc::math::Sin(a2+PI/2)-zc::math::Cos(pos2*PI*2/(dmisc2 == 0 ? 1 : dmisc2)))*abs(dmisc32);
18669 }
18670 else
18671 {
18672 guys.spr(i)->x = circle_x;
18673 guys.spr(i)->y = circle_y;
18674 }
18675
18676 temp_x=circle_x;
18677 temp_y=circle_y;
18678 }
18679
18680 double _MSVC2022_tmp1, _MSVC2022_tmp2;
18681 double ddir=atan2_MSVC2022_FIX(double(temp_y),double(temp_x));
18682
18683 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
18684 {
18685 guys.spr(i)->dir=l_down;
18686 }
18687 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
18688 {
18689 guys.spr(i)->dir=left;
18690 }
18691 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
18692 {
18693 guys.spr(i)->dir=l_up;
18694 }
18695 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
18696 {
18697 guys.spr(i)->dir=up;
18698 }
18699 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
18700 {
18701 guys.spr(i)->dir=r_up;
18702 }
18703 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
18704 {
18705 guys.spr(i)->dir=right;
18706 }
18707 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
18708 {
18709 guys.spr(i)->dir=r_down;
18710 }
18711 else
18712 {
18713 guys.spr(i)->dir=down;
18714 }
18715
18716 guys.spr(i)->x += x;
18717 guys.spr(i)->y = y-guys.spr(i)->y;
18718
18719 if((wpn>wEnemyWeapons || (wpn >= wScript1 && wpn <= wScript10)) && (dmisc5==2 || dmisc5== 3))
18720 {
18721 /*
18722 if(!(zc_oldrand()&127))
18723 {
18724 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID());
18725 sfx(wpnsfx(wpn),pan(int32_t(x)));
18726 }
18727 */
18728 if (((esPatra*)guys.spr(i))->clk5 < 0 && (editorflags & ENEMY_FLAG3))
18729 {
18730 if (((esPatra*)guys.spr(i))->clk4 <= 0 || ((esPatra*)guys.spr(i))->clk5 != -16) ++((esPatra*)guys.spr(i))->clk5;
18731 if (get_bit(quest_rules,qr_PATRAS_USE_HARDCODED_OFFSETS))
18732 {
18733 if (dmisc5 == 3)
18734 {
18735 if (((esPatra*)guys.spr(i))->clk5 >= 0) ((esPatra*)guys.spr(i))->o_tile=d->e_tile+120;
18736 else if (((esPatra*)guys.spr(i))->clk5 >= -16) ((esPatra*)guys.spr(i))->o_tile=d->e_tile+200;
18737 else if (((esPatra*)guys.spr(i))->clk5 >= -48) ((esPatra*)guys.spr(i))->o_tile=d->e_tile+160;
18738 else ((esPatra*)guys.spr(i))->o_tile=d->e_tile+120;
18739 }
18740 else
18741 {
18742 if (((esPatra*)guys.spr(i))->clk5 >= 0) ((esPatra*)guys.spr(i))->o_tile=d->e_tile+40;
18743 else if (((esPatra*)guys.spr(i))->clk5 >= -16) ((esPatra*)guys.spr(i))->o_tile=d->e_tile+120;
18744 else if (((esPatra*)guys.spr(i))->clk5 >= -48) ((esPatra*)guys.spr(i))->o_tile=d->e_tile+80;
18745 else ((esPatra*)guys.spr(i))->o_tile=d->e_tile+40;
18746 }
18747 }
18748 else
18749 {
18750 if (((esPatra*)guys.spr(i))->clk5 >= 0) ((esPatra*)guys.spr(i))->o_tile=d->s_tile;
18751 else if (((esPatra*)guys.spr(i))->clk5 >= -16) ((esPatra*)guys.spr(i))->o_tile=d->s_tile+80;
18752 else if (((esPatra*)guys.spr(i))->clk5 >= -48) ((esPatra*)guys.spr(i))->o_tile=d->s_tile+40;
18753 else ((esPatra*)guys.spr(i))->o_tile=d->s_tile;
18754 }
18755 }
18756 else if ((dmisc19 || ((esPatra*)guys.spr(i))->clk5) && (((esPatra*)guys.spr(i))->clk4 <= 0 || ((esPatra*)guys.spr(i))->clk5 != -16)) ++((esPatra*)guys.spr(i))->clk5;
18757 if (((esPatra*)guys.spr(i))->clk4 > 0) --((esPatra*)guys.spr(i))->clk4;
18758 if (!dmisc25 || (dmisc25 == 1 && !((enemy*)guys.spr(i))->superman) || ((dmisc25 == 2 || dmisc25 == 3) && ((enemy*)guys.spr(i))->superman))
18759 {
18760 switch(dmisc20) //Patra Attack Patterns
18761 {
18762 case 4: //Single one rapidfires
18763 {
18764 if (dofire && i == randeye)
18765 {
18766 ((esPatra*)guys.spr(i))->clk5 = -16;
18767 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES)) ((esPatra*)guys.spr(i))->clk5 = -48;
18768 ((esPatra*)guys.spr(i))->clk4 = 96;
18769 clk5 = -3;
18770 if (editorflags & ENEMY_FLAG6) clk4 = abs(clk5) + 16;
18771 }
18772 if (((esPatra*)guys.spr(i))->clk5 == -16 && (((esPatra*)guys.spr(i))->clk4 % 12) == 0)
18773 {
18774 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, guys.spr(i)->fakez);
18775 sfx(wpnsfx(wpn),pan(int32_t(x)));
18776 }
18777 break;
18778 }
18779 case 3: //Ring
18780 {
18781 if (dofire)
18782 {
18783 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES))
18784 {
18785 ((esPatra*)guys.spr(i))->clk5 = -48;
18786 clk5 = -48;
18787 if (editorflags & ENEMY_FLAG6) clk4 = 64;
18788 }
18789 else
18790 {
18791 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, guys.spr(i)->fakez);
18792 sfx(wpnsfx(wpn),pan(int32_t(x)));
18793 int32_t m=Ewpns.Count()-1;
18794 weapon *ew = (weapon*)(Ewpns.spr(m));
18795
18796 ew->setAngle(atan2(double(HeroY()-y),double(HeroX()-x)));
18797 ((esPatra*)guys.spr(i))->clk5 = 0;
18798 clk5 = 0;
18799 if (editorflags & ENEMY_FLAG6) clk4 = 16;
18800 }
18801 }
18802 if (((esPatra*)guys.spr(i))->clk5 == -16)
18803 {
18804 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, guys.spr(i)->fakez);
18805 sfx(wpnsfx(wpn),pan(int32_t(x)));
18806 int32_t m=Ewpns.Count()-1;
18807 weapon *ew = (weapon*)(Ewpns.spr(m));
18808
18809 ew->setAngle(atan2(double(HeroY()-y),double(HeroX()-x)));
18810 }
18811 break;
18812 }
18813 case 2: //one after another
18814 {
18815 if (dofire)
18816 {
18817 ((esPatra*)guys.spr(i))->clk5 = -48 - (12*(i-(index+flycnt+1)));
18818 clk5 = -48 - (12*flycnt2);
18819 if (editorflags & ENEMY_FLAG6) clk4 = abs(clk5) + 16;
18820 }
18821 if (((esPatra*)guys.spr(i))->clk5 == -16)
18822 {
18823 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, guys.spr(i)->fakez);
18824 sfx(wpnsfx(wpn),pan(int32_t(x)));
18825 }
18826 break;
18827 }
18828 case 1: //random one eye
18829 {
18830 if (dofire && i == randeye)
18831 {
18832 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES))
18833 {
18834 ((esPatra*)guys.spr(i))->clk5 = -48;
18835 clk5 = -48;
18836 if (editorflags & ENEMY_FLAG6) clk4 = 64;
18837 }
18838 else
18839 {
18840 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, guys.spr(i)->fakez);
18841 sfx(wpnsfx(wpn),pan(int32_t(x)));
18842 ((esPatra*)guys.spr(i))->clk5 = 0;
18843 clk5 = 0;
18844 if (editorflags & ENEMY_FLAG6) clk4 = 16;
18845 }
18846 }
18847 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES) && ((esPatra*)guys.spr(i))->clk5 == -16)
18848 {
18849 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, guys.spr(i)->fakez);
18850 sfx(wpnsfx(wpn),pan(int32_t(x)));
18851 }
18852 break;
18853 }
18854 default: //old behavior, all eyes can fire any time
18855 {
18856 if ((((dmisc18 && !(zc_oldrand() % zc_max(dmisc18, 1))) ||
18857 (!dmisc18 && !(zc_oldrand()&127))) && (((esPatra*)guys.spr(i))->clk5 >= 0 || !(editorflags & ENEMY_FLAG3) || !get_bit(quest_rules,qr_NEWENEMYTILES))
18858 && ((esPatra*)guys.spr(i))->clk5 >= dmisc19) && (!(editorflags & ENEMY_FLAG7) || (loopcnt == 0 &&
18859 (dmisc20 != 2 && (basesize*((int64_t)dmisc6 - (misc%dmisc6))) > 48))))
18860 {
18861 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES))
18862 {
18863 ((esPatra*)guys.spr(i))->clk5 = -48;
18864 if (editorflags & ENEMY_FLAG6) clk4 = 64;
18865 }
18866 else
18867 {
18868 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, fakez);
18869 sfx(wpnsfx(wpn),pan(int32_t(x)));
18870 ((esPatra*)guys.spr(i))->clk5 = 0;
18871 if (editorflags & ENEMY_FLAG6) clk4 = 16;
18872 }
18873 }
18874 if ((editorflags & ENEMY_FLAG3) && get_bit(quest_rules,qr_NEWENEMYTILES) && ((esPatra*)guys.spr(i))->clk5 == -16)
18875 {
18876 addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID(), 0, fakez);
18877 sfx(wpnsfx(wpn),pan(int32_t(x)));
18878 }
18879 break;
18880 }
18881 }
18882 }
18883 }
18884
18885 }
18886 }
18887 }
18888
18889 adjusted=true;
18890 return enemy::animate(index);
18891 }
18892
18893 void ePatra::FirePatraWeapon()
18894 { //.707
18895 int32_t xoff = 0;
18896 int32_t yoff = 0;
18897 if ( SIZEflags&guyflagOVERRIDE_HIT_WIDTH )
18898 {
18899 xoff += (hxsz/2)-8;
18900 //Z_scripterrlog("width flag enabled. xoff = %d\n", xoff);
18901 }
18902 if ( SIZEflags&guyflagOVERRIDE_HIT_HEIGHT )
18903 {
18904 yoff += (hysz/2)-8;
18905 //Z_scripterrlog("width flag enabled. yoff = %d\n", yoff);
18906 }
18907 sfx(wpnsfx(wpn),pan(int32_t(x)));
18908 switch (dmisc28)
18909 {
18910 case patrat8SHOT: //Fire Wizzrobe
18911 case patrat4SHOTDIAG:
18912 case patrat4SHOTRAND:
18913 if (dmisc28 != patrat4SHOTRAND || (zc_oldrand()%2)) //if it's the 4 shot rand type, only let it through half the time. Break is within so it doesn't do both, but if it skips this one it'll always do the other one.
18914 {
18915 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,l_up,-1, getUID(),false));
18916 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18917 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18918 if (wpn != ewFlame && wpn != ewFlame2) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= .707; //Fire already does this internall for asome bizarre reason.
18919
18920 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,l_down,-1, getUID(),false));
18921 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18922 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18923 if (wpn != ewFlame && wpn != ewFlame2) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= .707; //Fire already does this internall for asome bizarre reason.
18924
18925 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,r_up,-1, getUID(),false));
18926 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18927 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18928 if (wpn != ewFlame && wpn != ewFlame2) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= .707; //Fire already does this internall for asome bizarre reason.
18929
18930 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,r_down,-1, getUID(),false));
18931 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18932 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18933 if (wpn != ewFlame && wpn != ewFlame2) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= .707; //Fire already does this internall for asome bizarre reason.
18934
18935 if (dmisc28 == patrat4SHOTDIAG || dmisc28 == patrat4SHOTRAND) break;
18936 }
18937
18938 [[fallthrough]];
18939 case patrat4SHOTCARD: //Stalfos 3
18940 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,up,-1, getUID(),false));
18941 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18942 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18943 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,down,-1, getUID(),false));
18944 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18945 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18946 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,left,-1, getUID(),false));
18947 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18948 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18949 Ewpns.add(new weapon(x+xoff,y+yoff,z,wpn,1,wdp,right,-1, getUID(),false));
18950 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
18951 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->moveflags &= ~FLAG_CAN_PITFALL; //No falling in pits
18952 break;
18953
18954 default:
18955 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
18956 if (dmisc28 == patratBREATH) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->angle += (zc_rand(20,-20)/100.0)*PI;
18957 double anglestore = ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->angle;
18958 if (dmisc28 == patrat1SHOTFAST || dmisc28 == patrat3SHOTFAST || dmisc28 == patrat5SHOTFAST) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= 2;
18959 if (dmisc28 == patrat3SHOT || dmisc28 == patrat3SHOTFAST || dmisc28 == patrat5SHOT || dmisc28 == patrat5SHOTFAST)
18960 {
18961 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
18962 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->angle = anglestore + (double)0.46364761;
18963 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step += 0.1180;
18964 if (dmisc28 == patrat3SHOTFAST || dmisc28 == patrat5SHOTFAST) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= 2;
18965 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
18966 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->angle = anglestore - (double)0.46364761;
18967 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step += 0.1180;
18968 if (dmisc28 == patrat3SHOTFAST || dmisc28 == patrat5SHOTFAST) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= 2;
18969 if (dmisc28 == patrat5SHOT || dmisc28 == patrat5SHOTFAST)
18970 {
18971 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
18972 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->angle = anglestore + (double)0.78539816;
18973 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step += 0.4142;
18974 if (dmisc28 == patrat5SHOTFAST) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= 2;
18975 addEwpn(x,y,z,wpn,3,wdp,dir,getUID(), 0, fakez);
18976 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->angle = anglestore - (double)0.78539816;
18977 ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step += 0.4142;
18978 if (dmisc28 == patrat5SHOTFAST) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->step *= 2;
18979 }
18980 }
18981 break;
18982
18983 }
18984 sfx(wpnsfx(wpn),pan(int32_t(x)));
18985 //+0.46364761
18986 //11.80
18987 }
18988
18989 void ePatra::draw(BITMAP *dest)
18990 {
18991 tile=o_tile;
18992 update_enemy_frame();
18993 enemy::draw(dest);
18994 }
18995
18996 int32_t ePatra::defend(int32_t wpnId, int32_t *power, int32_t edef)
18997 {
18998 int32_t ret = enemy::defend(wpnId, power, edef);
18999
19000 if(ret < 0 && (flycnt||flycnt2))
19001 return 0;
19002
19003 return ret;
19004 }
19005
19006 int32_t ePatra::defendNew(int32_t wpnId, int32_t *power, int32_t edef, byte unblockable)
19007 {
19008 int32_t ret = enemy::defendNew(wpnId, power, edef, unblockable);
19009
19010 if(ret < 0 && (flycnt||flycnt2))
19011 return 0;
19012
19013 return ret;
19014 }
19015
19016 esPatra::esPatra(zfix X,zfix Y,int32_t Id,int32_t Clk, sprite * prnt) : enemy(X,Y,Id,Clk), parent(prnt)
19017 {
19018 //cs=8;
19019 item_set=0;
19020 misc=clk;
19021 clk4 = 0;
19022 clk5 = 0;
19023 clk = -((misc*21)>>1)-1;
19024 yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
19025 hxsz=12;
19026 hysz=12;
19027 hxofs=2;
19028 hyofs=2;
19029 extend = 0;
19030 txsz = 1;
19031 tysz = 1;
19032 /* //These need to be separate enemy editor fields. This enemy class also it's draw altered to correctly support big stuff.
19033 enemy *prntenemy = (enemy *) guys.getByUID(parent->getUID());
19034 int32_t prntSIZEflags = prntenemy->SIZEflags;
19035 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = prntenemy->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
19036 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
19037 // al_trace("Enemy txsz:%i\n", txsz);
19038 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = prntenemy->tysz; if ( tysz > 1 ) extend = 3; }
19039 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = prntenemy->hxsz;
19040 else
19041 hxsz=12;
19042 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = prntenemy->hysz;
19043 else
19044 hysz=12;
19045 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = prntenemy->hzsz;
19046 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = prntenemy->hxofs;
19047 else
19048 hxofs=2;
19049 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = prntenemy->hyofs;
19050 else hyofs=2;
19051 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
19052 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)prntenemy->xofs;
19053 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
19054 {
19055 yofs = (int32_t)prntenemy->yofs; //This seems to be setting to +48 or something with any value set?! -Z
19056 }
19057
19058 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)prntenemy->zofs;
19059 */
19060 mainguy=count_enemy=false;
19061 bgsfx=-1;
19062 //o_tile=0;
19063 flags &= (~guy_neverret);
19064 deadsfx = WAV_EDEAD;
19065 hitsfx = WAV_EHIT;
19066 isCore = false;
19067 }
19068
19069 bool esPatra::animate(int32_t index)
19070 {
19071 if(switch_hooked) return enemy::animate(index);
19072 if(dying)
19073 return Dead(index);
19074
19075 return enemy::animate(index);
19076 }
19077
19078 void esPatra::draw(BITMAP *dest)
19079 {
19080 if(get_bit(quest_rules,qr_NEWENEMYTILES))
19081 {
19082 tile = o_tile+(clk&3);
19083
19084 switch(dir) //directions get screwed up after 8. *shrug*
19085 {
19086 case up: //u
19087 flip=0;
19088 break;
19089
19090 case down: //d
19091 flip=0;
19092 tile+=4;
19093 break;
19094
19095 case left: //l
19096 flip=0;
19097 tile+=8;
19098 break;
19099
19100 case right: //r
19101 flip=0;
19102 tile+=12;
19103 break;
19104
19105 case l_up: //ul
19106 flip=0;
19107 tile+=20;
19108 break;
19109
19110 case r_up: //ur
19111 flip=0;
19112 tile+=24;
19113 break;
19114
19115 case l_down: //dl
19116 flip=0;
19117 tile+=28;
19118 break;
19119
19120 case r_down: //dr
19121 flip=0;
19122 tile+=32;
19123 break;
19124 }
19125 }
19126 else
19127 {
19128 tile = o_tile+((clk&2)>>1);
19129 }
19130
19131 if(clk>=0)
19132 enemy::draw(dest);
19133 }
19134
19135
19136 ePatraBS::ePatraBS(zfix ,zfix ,int32_t Id,int32_t Clk) : enemy((zfix)128,(zfix)48,Id,Clk)
19137 {
19138 adjusted=false;
19139 dir=(zc_oldrand()&7)+8;
19140 step=0.25;
19141 clk4 = 0;
19142 clk5 = 0;
19143 //flycnt=6; flycnt2=0;
19144 flycnt=dmisc1;
19145 flycnt2=0; // PatraBS doesn't have inner rings!
19146 loopcnt=0;
19147
19148 SIZEflags = d->SIZEflags;
19149 if ( ((SIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
19150 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
19151 // al_trace("Enemy txsz:%i\n", txsz);
19152 if ( ((SIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
19153 if ( ((SIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = d->hxsz;
19154 else hxsz = 32;
19155 if ( ((SIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = d->hysz;
19156 if ( ((SIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = d->hzsz;
19157 if ( (SIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = d->hxofs;
19158 else hxofs=-8;
19159 if ( (SIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = d->hyofs;
19160 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
19161 if ( (SIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)d->xofs;
19162 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
19163 {
19164 yofs = (int32_t)d->yofs; //This seems to be setting to +48 or something with any value set?! -Z
19165 yofs += (get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset) ; //this offset fixes yofs not plaing properly. -Z
19166 }
19167
19168 if ( (SIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) zofs = (int32_t)d->zofs;
19169
19170 if(dmisc6<int16_t(1))dmisc6=1; // ratio cannot be 0!
19171
19172 //nets+4480;
19173 }
19174
19175 bool ePatraBS::animate(int32_t index)
19176 {
19177 if(switch_hooked) return enemy::animate(index);
19178 if(dying)
19179 return Dead(index);
19180
19181 if(clk==0)
19182 {
19183 removearmos(x,y);
19184 }
19185
19186 variable_walk_8(rate,homing,hrate,spw_floater);
19187
19188 if(++clk2>90)
19189 {
19190 clk2=0;
19191
19192 if(loopcnt)
19193 --loopcnt;
19194 else
19195 {
19196 if((misc%dmisc6)==0)
19197 loopcnt=dmisc7;
19198 }
19199
19200 ++misc;
19201 }
19202
19203 // double size=1;;
19204 for(int32_t i=index+1; i<index+flycnt+1; i++)
19205 {
19206 if(!adjusted)
19207 {
19208 ((enemy*)guys.spr(i))->hp=dmisc3;
19209
19210 if(get_bit(quest_rules,qr_NEWENEMYTILES))
19211 {
19212 ((enemy*)guys.spr(i))->o_tile=o_tile+dmisc8;
19213 }
19214 else
19215 {
19216 ((enemy*)guys.spr(i))->o_tile=o_tile+1;
19217 }
19218
19219 ((enemy*)guys.spr(i))->cs = dmisc9;
19220 }
19221
19222 if(((enemy*)guys.spr(i))->hp <= 0)
19223 {
19224 for(int32_t j=i; j<index+flycnt+flycnt2; j++)
19225 {
19226 guys.swap(j,j+1);
19227 }
19228
19229 --flycnt;
19230 }
19231 else
19232 {
19233 int32_t pos2 = ((enemy*)guys.spr(i))->misc;
19234 double a2 = ((int64_t)clk2-pos2*90/(dmisc1==0?1:dmisc1))*PI/45;
19235 temp_x = zc::math::Cos(a2+PI/2)*45;
19236 temp_y = -zc::math::Sin(a2+PI/2)*45;
19237
19238 if(loopcnt>0)
19239 {
19240 guys.spr(i)->x = zc::math::Cos(a2+PI/2)*45;
19241 guys.spr(i)->y = (-zc::math::Sin(a2+PI/2)-zc::math::Cos(pos2*PI*2/(dmisc1==0?1:dmisc1)))*22.5;
19242 }
19243 else
19244 {
19245 guys.spr(i)->x = temp_x;
19246 guys.spr(i)->y = temp_y;
19247 }
19248
19249 double _MSVC2022_tmp1, _MSVC2022_tmp2;
19250 double ddir=atan2_MSVC2022_FIX(double(temp_y),double(temp_x));
19251
19252 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
19253 {
19254 guys.spr(i)->dir=l_down;
19255 }
19256 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
19257 {
19258 guys.spr(i)->dir=left;
19259 }
19260 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
19261 {
19262 guys.spr(i)->dir=l_up;
19263 }
19264 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
19265 {
19266 guys.spr(i)->dir=up;
19267 }
19268 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
19269 {
19270 guys.spr(i)->dir=r_up;
19271 }
19272 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
19273 {
19274 guys.spr(i)->dir=right;
19275 }
19276 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
19277 {
19278 guys.spr(i)->dir=r_down;
19279 }
19280 else
19281 {
19282 guys.spr(i)->dir=down;
19283 }
19284
19285 guys.spr(i)->x += x;
19286 guys.spr(i)->y += y;
19287 }
19288 }
19289
19290 adjusted=true;
19291 return enemy::animate(index);
19292 }
19293
19294 void ePatraBS::draw(BITMAP *dest)
19295 {
19296 tile=o_tile;
19297
19298 if(get_bit(quest_rules,qr_NEWENEMYTILES))
19299 {
19300 double _MSVC2022_tmp1, _MSVC2022_tmp2;
19301 double ddir=atan2_MSVC2022_FIX(double(y-(Hero.y)),double(Hero.x-x));
19302
19303 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
19304 {
19305 lookat=l_down;
19306 }
19307 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
19308 {
19309 lookat=down;
19310 }
19311 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
19312 {
19313 lookat=r_down;
19314 }
19315 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
19316 {
19317 lookat=right;
19318 }
19319 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
19320 {
19321 lookat=r_up;
19322 }
19323 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
19324 {
19325 lookat=up;
19326 }
19327 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
19328 {
19329 lookat=l_up;
19330 }
19331 else
19332 {
19333 lookat=left;
19334 }
19335
19336 switch(lookat) //directions get screwed up after 8. *shrug*
19337 {
19338 case up: //u
19339 flip=0;
19340 break;
19341
19342 case down: //d
19343 flip=0;
19344 tile+=8;
19345 break;
19346
19347 case left: //l
19348 flip=0;
19349 tile+=40;
19350 break;
19351
19352 case right: //r
19353 flip=0;
19354 tile+=48;
19355 break;
19356
19357 case l_up: //ul
19358 flip=0;
19359 tile+=80;
19360 break;
19361
19362 case r_up: //ur
19363 flip=0;
19364 tile+=88;
19365 break;
19366
19367 case l_down: //dl
19368 flip=0;
19369 tile+=120;
19370 break;
19371
19372 case r_down: //dr
19373 flip=0;
19374 tile+=128;
19375 break;
19376 }
19377
19378 tile+=(2*(clk&3));
19379 xofs-=8;
19380 yofs-=8;
19381 drawblock(dest,15);
19382 xofs+=8;
19383 yofs+=8;
19384 }
19385 else
19386 {
19387 flip=(clk&1);
19388 xofs-=8;
19389 yofs-=8;
19390 enemy::draw(dest);
19391 xofs+=16;
19392 enemy::draw(dest);
19393 yofs+=16;
19394 enemy::draw(dest);
19395 xofs-=16;
19396 enemy::draw(dest);
19397 xofs+=8;
19398 yofs-=8;
19399 }
19400 }
19401
19402 int32_t ePatraBS::defend(int32_t wpnId, int32_t *power, int32_t edef)
19403 {
19404 int32_t ret = enemy::defend(wpnId, power, edef);
19405
19406 if(ret < 0 && (flycnt||flycnt2))
19407 return 0;
19408
19409 return ret;
19410 }
19411
19412 int32_t ePatraBS::defendNew(int32_t wpnId, int32_t *power, int32_t edef, byte unblockable)
19413 {
19414 int32_t ret = enemy::defendNew(wpnId, power, edef, unblockable);
19415
19416 if(ret < 0 && (flycnt||flycnt2))
19417 return 0;
19418
19419 return ret;
19420 }
19421
19422 esPatraBS::esPatraBS(zfix X,zfix Y,int32_t Id,int32_t Clk, sprite * prnt) : enemy(X,Y,Id,Clk), parent(prnt)
19423 {
19424 //cs=csBOSS;
19425 item_set=0;
19426 misc=clk;
19427 clk = -((misc*21)>>1)-1;
19428 clk4 = 0;
19429 clk5 = 0;
19430 enemy *prntenemy = (enemy *) guys.getByUID(parent->getUID());
19431 int32_t prntSIZEflags = prntenemy->SIZEflags;
19432 if ( ((prntSIZEflags&guyflagOVERRIDE_TILE_WIDTH) != 0) && txsz > 0 ) { txsz = prntenemy->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
19433 //al_trace("->txsz:%i\n", txsz); Verified that this is setting the value. -Z
19434 // al_trace("Enemy txsz:%i\n", txsz);
19435 if ( ((prntSIZEflags&guyflagOVERRIDE_TILE_HEIGHT) != 0) && tysz > 0 ) { tysz = prntenemy->tysz; if ( tysz > 1 ) extend = 3; }
19436 if ( ((prntSIZEflags&guyflagOVERRIDE_HIT_WIDTH) != 0) && hxsz >= 0 ) hxsz = prntenemy->hxsz;
19437 else hxsz=16;
19438 if ( ((prntSIZEflags&guyflagOVERRIDE_HIT_HEIGHT) != 0) && hysz >= 0 ) hysz = prntenemy->hysz;
19439 else hysz=16;
19440 if ( ((prntSIZEflags&guyflagOVERRIDE_HIT_Z_HEIGHT) != 0) && hzsz >= 0 ) hzsz = prntenemy->hzsz;
19441 if ( (prntSIZEflags&guyflagOVERRIDE_HIT_X_OFFSET) != 0 ) hxofs = prntenemy->hxofs;
19442 if ( (prntSIZEflags&guyflagOVERRIDE_HIT_Y_OFFSET) != 0 ) hyofs = prntenemy->hyofs;
19443 else hyofs=2;
19444 // if ( (SIZEflags&guyflagOVERRIDEHITZOFFSET) != 0 ) hzofs = hzofs;
19445 if ( (prntSIZEflags&guyflagOVERRIDE_DRAW_X_OFFSET) != 0 ) xofs = (int32_t)prntenemy->xofs;
19446 if ( (prntSIZEflags&guyflagOVERRIDE_DRAW_Y_OFFSET) != 0 )
19447 {
19448 yofs = (int32_t)prntenemy->yofs;
19449 }
19450 else yofs=(get_bit(quest_rules, qr_OLD_DRAWOFFSET)?playing_field_offset:original_playing_field_offset);
19451 if ( (prntSIZEflags&guyflagOVERRIDE_DRAW_Z_OFFSET) != 0 ) prntenemy->zofs = (int32_t)zofs;
19452
19453 bgsfx=-1;
19454 mainguy=count_enemy=false;
19455 deadsfx = WAV_EDEAD;
19456 hitsfx = WAV_EHIT;
19457 flags &= ~guy_neverret;
19458 isCore = false;
19459 }
19460
19461 bool esPatraBS::animate(int32_t index)
19462 {
19463 if(switch_hooked) return enemy::animate(index);
19464 if(dying)
19465 return Dead(index);
19466
19467 return enemy::animate(index);
19468 }
19469
19470 void esPatraBS::draw(BITMAP *dest)
19471 {
19472 tile=o_tile;
19473
19474 if(get_bit(quest_rules,qr_NEWENEMYTILES))
19475 {
19476 switch(dir) //directions get screwed up after 8. *shrug*
19477 {
19478 case up: //u
19479 flip=0;
19480 break;
19481
19482 case down: //d
19483 flip=0;
19484 tile+=4;
19485 break;
19486
19487 case left: //l
19488 flip=0;
19489 tile+=8;
19490 break;
19491
19492 case right: //r
19493 flip=0;
19494 tile+=12;
19495 break;
19496
19497 case l_up: //ul
19498 flip=0;
19499 tile+=20;
19500 break;
19501
19502 case r_up: //ur
19503 flip=0;
19504 tile+=24;
19505 break;
19506
19507 case l_down: //dl
19508 flip=0;
19509 tile+=28;
19510 break;
19511
19512 case r_down: //dr
19513 flip=0;
19514 tile+=32;
19515 break;
19516 }
19517
19518 tile += ((clk&6)>>1);
19519 }
19520 else
19521 {
19522 tile += (clk&4)?1:0;
19523 }
19524
19525 if(clk>=0)
19526 enemy::draw(dest);
19527 }
19528
19529
19530 /**********************************/
19531 /********** Misc Code ***********/
19532 /**********************************/
19533
19534 void addEwpn(int32_t x,int32_t y,int32_t z,int32_t id,int32_t type,int32_t power,int32_t dir, int32_t parentid, byte script_generated, int32_t fakez)
19535 {
19536 if(id>wEnemyWeapons || (id >= wScript1 && id <= wScript10))
19537 Ewpns.add(new weapon((zfix)x,(zfix)y,(zfix)z,id,type,power,dir, -1, parentid, script_generated));
19538 if (fakez > 0) ((weapon*)(Ewpns.spr(Ewpns.Count()-1)))->fakez = fakez;
19539 }
19540
19541 1 int32_t hit_enemy(int32_t index, int32_t wpnId,int32_t power,int32_t wpnx,int32_t wpny,int32_t dir, int32_t enemyHitWeapon)
19542 {
19543 // Kludge
19544
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 weapon *w = new weapon((zfix)wpnx,(zfix)wpny,(zfix)0,wpnId,0,power,dir,enemyHitWeapon,-1,false);
19545 1 int32_t ret= ((enemy*)guys.spr(index))->takehit(w);
19546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 delete w;
19547 1 return ret;
19548 }
19549
19550 void enemy_scored(int32_t index)
19551 {
19552 ((enemy*)guys.spr(index))->scored=true;
19553 }
19554
19555 3 void addguy(int32_t x,int32_t y,int32_t id,int32_t clk,bool mainguy)
19556 {
19557
6/12
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 guy *g = new guy((zfix)x,(zfix)(y+(isdungeon()?1:0)),id,get_bit(quest_rules,qr_NOGUYPOOF)?0:clk,mainguy);
19558 3 guys.add(g);
19559 3 }
19560
19561 1 void additem(int32_t x,int32_t y,int32_t id,int32_t pickup)
19562 {
19563
5/10
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1 item *i = new item(zfix(x), zfix(y - get_bit(quest_rules, qr_NOITEMOFFSET)), zfix(0), id, pickup, 0);
19564 1 items.add(i);
19565 1 }
19566
19567 void additem(int32_t x,int32_t y,int32_t id,int32_t pickup,int32_t clk)
19568 {
19569 item *i = new item((zfix)x,(zfix)y-(get_bit(quest_rules, qr_NOITEMOFFSET)),(zfix)0,id,pickup,clk);
19570 items.add(i);
19571 }
19572
19573 void adddummyitem(int32_t x,int32_t y,int32_t id,int32_t pickup)
19574 {
19575 item *i = new item((zfix)x,(zfix)y-(get_bit(quest_rules, qr_NOITEMOFFSET)),(zfix)0,id,pickup,0,true);
19576 items.add(i);
19577 }
19578
19579 void kill_em_all()
19580 {
19581 for(int32_t i=0; i<guys.Count(); i++)
19582 {
19583 enemy *e = ((enemy*)guys.spr(i));
19584
19585 if(e->flags&(1<<3) && !(e->family == eeGHINI && e->dmisc1 == 1)) continue;
19586
19587 e->kickbucket();
19588 }
19589 }
19590
19591 bool can_kill_em_all()
19592 {
19593 for(int32_t i=0; i<guys.Count(); i++)
19594 {
19595 enemy *e = ((enemy*)guys.spr(i));
19596
19597 if(e->flags&(1<<3) && !(e->family == eeGHINI && e->dmisc1 == 1)) continue;
19598 if(e->superman) continue;
19599 return true;
19600 }
19601 return false;
19602 }
19603
19604 //This needs a quest rule, or enemy flag, Dying Enemy Doesn't Hurt Hero
19605 // For Hero's hit detection. Don't count them if they are stunned or are guys.
19606 int32_t GuyHit(int32_t tx,int32_t ty,int32_t tz,int32_t txsz,int32_t tysz,int32_t tzsz)
19607 {
19608 for(int32_t i=0; i<guys.Count(); i++)
19609 {
19610 if(guys.spr(i)->hit(tx,ty,tz,txsz,tysz,tzsz))
19611 {
19612 if(((enemy*)guys.spr(i))->stunclk==0 && ((enemy*)guys.spr(i))->frozenclock==0 && (!get_bit(quest_rules, qr_SAFEENEMYFADE) || ((enemy*)guys.spr(i))->fading != fade_flicker)
19613 &&(((enemy*)guys.spr(i))->d->family != eeGUY || ((enemy*)guys.spr(i))->dmisc1))
19614 {
19615 return i;
19616 }
19617 }
19618 }
19619
19620 return -1;
19621 }
19622
19623 1653 int32_t GuyHitFrom(int32_t index,int32_t tx,int32_t ty,int32_t tz,int32_t txsz,int32_t tysz,int32_t tzsz)
19624 {
19625
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
✓ Branch 2 taken 3064 times.
✓ Branch 3 taken 1653 times.
4717 for(int32_t i=zc_max(0, index); i<guys.Count(); i++)
19626 {
19627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3064 times.
3064 if(guys.spr(i)->hit(tx,ty,tz,txsz,tysz,tzsz))
19628 {
19629 return i;
19630 }
19631 3064 }
19632
19633 1653 return -1;
19634 1653 }
19635
19636 // For Hero's hit detection. Count them if they are dying.
19637 1 int32_t GuyHit(int32_t index,int32_t tx,int32_t ty,int32_t tz,int32_t txsz,int32_t tysz,int32_t tzsz)
19638 {
19639 1 enemy *e = (enemy*)guys.spr(index);
19640
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if(!e || e->hp > 0)
19641 return -1;
19642
19643 1 bool d = e->dying;
19644 1 int32_t hc = e->hclk;
19645 1 e->dying = false;
19646 1 e->hclk = 0;
19647 1 bool hit = e->hit(tx,ty,tz,txsz,tysz,tzsz);
19648 1 e->dying = d;
19649 1 e->hclk = hc;
19650
19651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return hit ? index : -1;
19652 1 }
19653
19654 1888 bool hasMainGuy()
19655 {
19656
2/2
✓ Branch 0 taken 2235 times.
✓ Branch 1 taken 679 times.
2914 for(int32_t i=0; i<guys.Count(); i++)
19657 {
19658
2/2
✓ Branch 0 taken 1209 times.
✓ Branch 1 taken 1026 times.
2235 if(((enemy*)guys.spr(i))->mainguy)
19659 {
19660 1209 return true;
19661 }
19662 1026 }
19663
19664 679 return false;
19665 1888 }
19666
19667 void EatHero(int32_t index)
19668 {
19669 ((eStalfos*)guys.spr(index))->eathero();
19670 }
19671
19672 void GrabHero(int32_t index)
19673 {
19674 ((eWallM*)guys.spr(index))->grabhero();
19675 }
19676
19677 bool CarryHero()
19678 {
19679 for(int32_t i=0; i<guys.Count(); i++)
19680 {
19681 if(((guy*)(guys.spr(i)))->family==eeWALLM)
19682 {
19683 if(((eWallM*)guys.spr(i))->hashero)
19684 {
19685 Hero.x=guys.spr(i)->x;
19686 Hero.y=guys.spr(i)->y;
19687 return ((eWallM*)guys.spr(i))->misc > 0;
19688 }
19689 }
19690
19691 // Like Likes currently can't carry Hero.
19692 /*
19693 if(((guy*)(guys.spr(i)))->family==eeLIKE)
19694 {
19695 if(((eLikeLike*)guys.spr(i))->hashero)
19696 {
19697 Hero.x=guys.spr(i)->x;
19698 Hero.y=guys.spr(i)->y;
19699 return (true);
19700 }
19701 }*/
19702 }
19703
19704 return false;
19705 }
19706
19707 // Move item with guy
19708 void movefairy(zfix &x,zfix &y,int32_t misc)
19709 {
19710 int32_t i = guys.idFirst(eITEMFAIRY+0x1000*misc);
19711
19712 if(i!=-1)
19713 {
19714 x = guys.spr(i)->x;
19715 y = guys.spr(i)->y;
19716 }
19717 }
19718
19719 // Move guy with item (used by FFC scripts and hookshot-dragged fairies)
19720 void movefairy2(zfix x,zfix y,int32_t misc)
19721 {
19722 int32_t i = guys.idFirst(eITEMFAIRY+0x1000*misc);
19723
19724 if(i!=-1)
19725 {
19726 guys.spr(i)->x = x;
19727 guys.spr(i)->y = y;
19728 }
19729 }// Move item with guy
19730
19731 void movefairynew(zfix &x,zfix &y, item const &itemfairy)
19732 {
19733 enemy *fairy = (enemy *) guys.getByUID(itemfairy.fairyUID);
19734
19735 if(fairy)
19736 {
19737 x = fairy->x;
19738 y = fairy->y;
19739 }
19740 }
19741
19742 // Move guy with item (used by FFC scripts and hookshot-dragged fairies)
19743 void movefairynew2(zfix x,zfix y, item const &itemfairy)
19744 {
19745 enemy *fairy = (enemy *) guys.getByUID(itemfairy.fairyUID);
19746
19747 if(fairy)
19748 {
19749 fairy->x = x;
19750 fairy->y = y;
19751 }
19752 }
19753
19754 void killfairy(int32_t misc)
19755 {
19756 int32_t i = guys.idFirst(eITEMFAIRY+0x1000*misc);
19757 guys.del(i);
19758 }
19759
19760 int32_t getGuyIndex(const int32_t eid)
19761 {
19762 for(word i = 0; i < guys.Count(); i++)
19763 {
19764 if(guys.spr(i)->getUID() == eid)
19765 return i;
19766 }
19767
19768 return -1;
19769 }
19770
19771 void killfairynew(item const &itemfairy)
19772 {
19773 enemy *fairy = (enemy *) guys.getByUID(itemfairy.fairyUID);
19774 if (fairy != NULL) guys.del(getGuyIndex(itemfairy.fairyUID));
19775 }
19776
19777 //Should probably change this to return an 'enemy*', null on failure -Em
19778 4 int32_t addenemy(int32_t x,int32_t y,int32_t id,int32_t clk)
19779 {
19780 4 return addenemy(x,y,0,id,clk);
19781 }
19782
19783 int32_t addchild(int32_t x,int32_t y,int32_t id,int32_t clk, int32_t parent_scriptUID)
19784 {
19785 return addchild(x,y,0,id,clk, parent_scriptUID);
19786 }
19787
19788 int32_t addchild(int32_t x,int32_t y,int32_t z,int32_t id,int32_t clk, int32_t parent_scriptUID)
19789 {
19790 if(id <= 0) return 0;
19791
19792 int32_t ret = 0;
19793 sprite *e=NULL;
19794 al_trace("Adding child\n");
19795
19796 switch(guysbuf[id&0xFFF].family)
19797 {
19798 //Fixme: possible enemy memory leak. (minor)
19799 case eeWALK:
19800 e = new eStalfos((zfix)x,(zfix)y,id,clk);
19801 break;
19802
19803 case eeLEV:
19804 e = new eLeever((zfix)x,(zfix)y,id,clk);
19805 break;
19806
19807 case eeTEK:
19808 e = new eTektite((zfix)x,(zfix)y,id,clk);
19809 break;
19810
19811 case eePEAHAT:
19812 e = new ePeahat((zfix)x,(zfix)y,id,clk);
19813 break;
19814
19815 case eeZORA:
19816 e = new eZora((zfix)x,(zfix)y,id,clk);
19817 break;
19818
19819 case eeGHINI:
19820 e = new eGhini((zfix)x,(zfix)y,id,clk);
19821 break;
19822
19823 case eeKEESE:
19824 e = new eKeese((zfix)x,(zfix)y,id,clk);
19825 break;
19826
19827 case eeWIZZ:
19828 e = new eWizzrobe((zfix)x,(zfix)y,id,clk);
19829 break;
19830
19831 case eePROJECTILE:
19832 e = new eProjectile((zfix)x,(zfix)y,id,clk);
19833 break;
19834
19835 case eeWALLM:
19836 e = new eWallM((zfix)x,(zfix)y,id,clk);
19837 break;
19838
19839 case eeAQUA:
19840 e = new eAquamentus((zfix)x,(zfix)y,id,clk);
19841 break;
19842
19843 case eeMOLD:
19844 e = new eMoldorm((zfix)x,(zfix)y,id,zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)));
19845 break;
19846
19847 case eeMANHAN:
19848 e = new eManhandla((zfix)x,(zfix)y,id,clk);
19849 break;
19850
19851 case eeGLEEOK:
19852 e = new eGleeok((zfix)x,(zfix)y,id,zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)));
19853 break;
19854
19855 case eeGHOMA:
19856 e = new eGohma((zfix)x,(zfix)y,id,clk);
19857 break;
19858
19859 case eeLANM:
19860 e = new eLanmola((zfix)x,(zfix)y,id,zc_max(1,zc_min(253,guysbuf[id&0xFFF].misc1)));
19861 break;
19862
19863 case eeGANON:
19864 e = new eGanon((zfix)x,(zfix)y,id,clk);
19865 break;
19866
19867 case eeFAIRY:
19868 e = new eItemFairy((zfix)x,(zfix)y,id+0x1000*clk,clk);
19869 break;
19870
19871 case eeFIRE:
19872 e = new eFire((zfix)x,(zfix)y,id,clk);
19873 break;
19874
19875 case eeOTHER:
19876 e = new eOther((zfix)x,(zfix)y,id,clk);
19877 break;
19878
19879
19880 case eeSCRIPT01:
19881 case eeSCRIPT02:
19882 case eeSCRIPT03:
19883 case eeSCRIPT04:
19884 case eeSCRIPT05:
19885 case eeSCRIPT06:
19886 case eeSCRIPT07:
19887 case eeSCRIPT08:
19888 case eeSCRIPT09:
19889 case eeSCRIPT10:
19890 case eeSCRIPT11:
19891 case eeSCRIPT12:
19892 case eeSCRIPT13:
19893 case eeSCRIPT14:
19894 case eeSCRIPT15:
19895 case eeSCRIPT16:
19896 case eeSCRIPT17:
19897 case eeSCRIPT18:
19898 case eeSCRIPT19:
19899 case eeSCRIPT20:
19900 {
19901 if ( !get_bit(quest_rules, qr_SCRIPT_FRIENDLY_ENEMY_TYPES) )
19902 {
19903 e = new eScript((zfix)x,(zfix)y,id,clk);
19904 break;
19905 }
19906 else return 0;
19907 }
19908
19909 case eeFFRIENDLY01:
19910 case eeFFRIENDLY02:
19911 case eeFFRIENDLY03:
19912 case eeFFRIENDLY04:
19913 case eeFFRIENDLY05:
19914 case eeFFRIENDLY06:
19915 case eeFFRIENDLY07:
19916 case eeFFRIENDLY08:
19917 case eeFFRIENDLY09:
19918 case eeFFRIENDLY10:
19919 {
19920 if ( !get_bit(quest_rules, qr_SCRIPT_FRIENDLY_ENEMY_TYPES) )
19921 {
19922 e = new eFriendly((zfix)x,(zfix)y,id,clk); break;
19923 }
19924 else return 0;
19925
19926 }
19927
19928 case eeSPINTILE:
19929 e = new eSpinTile((zfix)x,(zfix)y,id,clk);
19930 break;
19931
19932 // and these enemies use the misc10/misc2 value
19933 case eeROCK:
19934 {
19935 switch(guysbuf[id&0xFFF].misc10)
19936 {
19937 case 1:
19938 e = new eBoulder((zfix)x,(zfix)y,id,clk);
19939 break;
19940
19941 case 0:
19942 default:
19943 e = new eRock((zfix)x,(zfix)y,id,clk);
19944 break;
19945 }
19946
19947 break;
19948 }
19949
19950 case eeTRAP:
19951 {
19952 switch(guysbuf[id&0xFFF].misc2)
19953 {
19954 case 1:
19955 e = new eTrap2((zfix)x,(zfix)y,id,clk);
19956 break;
19957
19958 case 0:
19959 default:
19960 e = new eTrap((zfix)x,(zfix)y,id,clk);
19961 break;
19962 }
19963
19964 break;
19965 }
19966
19967 case eeDONGO:
19968 {
19969 switch(guysbuf[id&0xFFF].misc10)
19970 {
19971 case 1:
19972 e = new eDodongo2((zfix)x,(zfix)y,id,clk);
19973 break;
19974
19975 case 0:
19976 default:
19977 e = new eDodongo((zfix)x,(zfix)y,id,clk);
19978 break;
19979 }
19980
19981 break;
19982 }
19983
19984 case eeDIG:
19985 {
19986 switch(guysbuf[id&0xFFF].misc10)
19987 {
19988 case 1:
19989 e = new eLilDig((zfix)x,(zfix)y,id,clk);
19990 break;
19991
19992 case 0:
19993 default:
19994 e = new eBigDig((zfix)x,(zfix)y,id,clk);
19995 break;
19996 }
19997
19998 break;
19999 }
20000
20001 case eePATRA:
20002 {
20003 switch(guysbuf[id&0xFFF].misc10)
20004 {
20005 case 1:
20006 if (get_bit(quest_rules,qr_HARDCODED_BS_PATRA))
20007 {
20008 e = new ePatraBS((zfix)x,(zfix)y,id,clk);
20009 break;
20010 }
20011 [[fallthrough]];
20012 case 0:
20013 default:
20014 e = new ePatra((zfix)x,(zfix)y,id,clk);
20015 break;
20016 }
20017
20018 break;
20019 }
20020
20021 case eeGUY:
20022 {
20023 switch(guysbuf[id&0xFFF].misc10)
20024 {
20025 case 1:
20026 e = new eTrigger((zfix)x,(zfix)y,id,clk);
20027 break;
20028
20029 case 0:
20030 default:
20031 e = new eNPC((zfix)x,(zfix)y,id,clk);
20032 break;
20033 }
20034
20035 break;
20036 }
20037
20038 case eeNONE:
20039 if(guysbuf[id&0xFFF].misc10 ==1)
20040 {
20041 e = new eTrigger((zfix)x,(zfix)y,id,clk);
20042 break;
20043 break;
20044 }
20045 [[fallthrough]];
20046 default:
20047
20048 return 0;
20049 }
20050
20051 ret++; // Made one enemy.
20052
20053 if(z && canfall(id))
20054 {
20055 e->z = (zfix)z;
20056 }
20057
20058 ((enemy*)e)->ceiling = (z && canfall(id));
20059 ((enemy*)e)->parent_script_UID = parent_scriptUID;
20060 //al_trace("Child Script UID: %d\n",((enemy*)e)->script_UID);
20061 //zprint2("Child Script UID: %d\n",((enemy*)e)->script_UID);
20062 //al_trace("Child's Parent UID: %d\n",((enemy*)e)->parent_script_UID);
20063 //zprint2("Child's Parent UID: %d\n",((enemy*)e)->parent_script_UID);
20064
20065
20066 if(!guys.add(e))
20067 {
20068 return 0;
20069 }
20070
20071 // add segments of segmented enemies
20072 int32_t c=0;
20073
20074 switch(guysbuf[id&0xFFF].family)
20075 {
20076 case eeMOLD:
20077 {
20078 byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
20079 id &= 0xFFF;
20080
20081 for(int32_t i=0; i<zc_max(1,zc_min(254,guysbuf[id].misc1)); i++)
20082 {
20083 //christ this is messy -DD
20084 int32_t segclk = -i*((int32_t)(8.0/(zslongToFix(guysbuf[id&0xFFF].step*100))));
20085
20086 if(!guys.add(new esMoldorm((zfix)x,(zfix)y,id+0x1000,segclk)))
20087 {
20088 al_trace("Moldorm segment %d could not be created!\n",i+1);
20089
20090 for(int32_t j=0; j<i+1; j++)
20091 guys.del(guys.Count()-1);
20092
20093 return 0;
20094 }
20095
20096 if(i>0)
20097 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
20098
20099 ret++;
20100 }
20101
20102 break;
20103 }
20104
20105 case eeLANM:
20106 {
20107 id &= 0xFFF;
20108 int32_t shft = guysbuf[id].misc2;
20109 byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
20110
20111 if(!guys.add(new esLanmola((zfix)x,(zfix)y,id+0x1000,0)))
20112 {
20113 al_trace("Lanmola segment 1 could not be created!\n");
20114 guys.del(guys.Count()-1);
20115 return 0;
20116 }
20117
20118 ret++;
20119
20120 for(int32_t i=1; i<zc_max(1,zc_min(253,guysbuf[id&0xFFF].misc1)); i++)
20121 {
20122 if(!guys.add(new esLanmola((zfix)x,(zfix)y,id+0x2000,-(i<<shft))))
20123 {
20124 al_trace("Lanmola segment %d could not be created!\n",i+1);
20125
20126 for(int32_t j=0; j<i+1; j++)
20127 guys.del(guys.Count()-1);
20128
20129 return 0;
20130 }
20131
20132 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
20133 ret++;
20134 }
20135 }
20136 break;
20137
20138 case eeMANHAN:
20139 id &= 0xFFF;
20140
20141 for(int32_t i=0; i<((!(guysbuf[id].misc2))?4:8); i++)
20142 {
20143 if(!guys.add(new esManhandla((zfix)x,(zfix)y,id+0x1000,i)))
20144 {
20145 al_trace("Manhandla head %d could not be created!\n",i+1);
20146
20147 for(int32_t j=0; j<i+1; j++)
20148 {
20149 guys.del(guys.Count()-1);
20150 }
20151
20152 return 0;
20153 }
20154
20155 ret++;
20156 ((enemy*)guys.spr(guys.Count()-1))->frate=guysbuf[id].misc1;
20157 }
20158
20159 break;
20160
20161 case eeGLEEOK:
20162 {
20163 id &= 0xFFF;
20164
20165 for(int32_t i=0; i<zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)); i++)
20166 {
20167 if(!guys.add(new esGleeok((zfix)x,(zfix)y,id+0x1000,c, e)))
20168 {
20169 al_trace("Gleeok head %d could not be created!\n",i+1);
20170
20171 for(int32_t j=0; j<i+1; j++)
20172 {
20173 guys.del(guys.Count()-1);
20174 }
20175
20176 return false;
20177 }
20178
20179 c-=guysbuf[id].misc4;
20180 ret++;
20181 }
20182 }
20183 break;
20184
20185
20186 case eePATRA:
20187 {
20188 id &= 0xFFF;
20189 int32_t outeyes = 0;
20190
20191 for(int32_t i=0; i<zc_min(254,guysbuf[id&0xFFF].misc1); i++)
20192 {
20193 if(!((guysbuf[id].misc10&&get_bit(quest_rules,qr_HARDCODED_BS_PATRA))?guys.add(new esPatraBS((zfix)x,(zfix)y,id+0x1000,i,e)):guys.add(new esPatra((zfix)x,(zfix)y,id+0x1000,i,e))))
20194 {
20195 al_trace("Patra outer eye %d could not be created!\n",i+1);
20196
20197 for(int32_t j=0; j<i+1; j++)
20198 guys.del(guys.Count()-1);
20199
20200 return 0;
20201 }
20202 else
20203 outeyes++;
20204
20205 ret++;
20206 }
20207
20208 for(int32_t i=0; i<zc_min(254,guysbuf[id&0xFFF].misc2); i++)
20209 {
20210 if(!guys.add(new esPatra((zfix)x,(zfix)y,id+0x1000,i,e)))
20211 {
20212 al_trace("Patra inner eye %d could not be created!\n",i+1);
20213
20214 for(int32_t j=0; j<i+1+zc_min(254,outeyes); j++)
20215 guys.del(guys.Count()-1);
20216
20217 return 0;
20218 }
20219
20220 ret++;
20221 }
20222
20223 break;
20224 }
20225 }
20226
20227 return ret;
20228 }
20229
20230 // Returns number of enemies/segments created
20231 12 int32_t addenemy(int32_t x,int32_t y,int32_t z,int32_t id,int32_t clk)
20232 {
20233 //zprint2("addenemy id is: %d\n", (id&0xFFF));
20234 12 int32_t realid = id&0xFFF;
20235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if( realid > MAXGUYS )
20236 {
20237 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "addenemy()");
20238 return 0;
20239 }
20240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(id <= 0) return 0;
20241
20242 12 int32_t ret = 0;
20243 12 sprite *e=NULL;
20244
20245
2/31
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
12 switch(guysbuf[id&0xFFF].family)
20246 {
20247 //Fixme: possible enemy memory leak. (minor)
20248 case eeWALK:
20249
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 e = new eStalfos((zfix)x,(zfix)y,id,clk);
20250 8 break;
20251
20252 case eeLEV:
20253 e = new eLeever((zfix)x,(zfix)y,id,clk);
20254 break;
20255
20256 case eeTEK:
20257
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 e = new eTektite((zfix)x,(zfix)y,id,clk);
20258 4 break;
20259
20260 case eePEAHAT:
20261 e = new ePeahat((zfix)x,(zfix)y,id,clk);
20262 break;
20263
20264 case eeZORA:
20265 e = new eZora((zfix)x,(zfix)y,id,clk);
20266 break;
20267
20268 case eeGHINI:
20269 e = new eGhini((zfix)x,(zfix)y,id,clk);
20270 break;
20271
20272 case eeKEESE:
20273 e = new eKeese((zfix)x,(zfix)y,id,clk);
20274 break;
20275
20276 case eeWIZZ:
20277 e = new eWizzrobe((zfix)x,(zfix)y,id,clk);
20278 break;
20279
20280 case eePROJECTILE:
20281 e = new eProjectile((zfix)x,(zfix)y,id,clk);
20282 break;
20283
20284 case eeWALLM:
20285 e = new eWallM((zfix)x,(zfix)y,id,clk);
20286 break;
20287
20288 case eeAQUA:
20289 e = new eAquamentus((zfix)x,(zfix)y,id,clk);
20290 break;
20291
20292 case eeMOLD:
20293 e = new eMoldorm((zfix)x,(zfix)y,id,zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)));
20294 break;
20295
20296 case eeMANHAN:
20297 e = new eManhandla((zfix)x,(zfix)y,id,clk);
20298 break;
20299
20300 case eeGLEEOK:
20301 e = new eGleeok((zfix)x,(zfix)y,id,zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)));
20302 break;
20303
20304 case eeGHOMA:
20305 e = new eGohma((zfix)x,(zfix)y,id,clk);
20306 break;
20307
20308 case eeLANM:
20309 e = new eLanmola((zfix)x,(zfix)y,id,zc_max(1,zc_min(253,guysbuf[id&0xFFF].misc1)));
20310 break;
20311
20312 case eeGANON:
20313 e = new eGanon((zfix)x,(zfix)y,id,clk);
20314 break;
20315
20316 case eeFAIRY:
20317 e = new eItemFairy((zfix)x,(zfix)y,id+0x1000*clk,clk);
20318 break;
20319
20320 case eeFIRE:
20321 e = new eFire((zfix)x,(zfix)y,id,clk);
20322 break;
20323
20324 case eeOTHER:
20325 e = new eOther((zfix)x,(zfix)y,id,clk);
20326 break;
20327
20328
20329 case eeSCRIPT01:
20330 case eeSCRIPT02:
20331 case eeSCRIPT03:
20332 case eeSCRIPT04:
20333 case eeSCRIPT05:
20334 case eeSCRIPT06:
20335 case eeSCRIPT07:
20336 case eeSCRIPT08:
20337 case eeSCRIPT09:
20338 case eeSCRIPT10:
20339 case eeSCRIPT11:
20340 case eeSCRIPT12:
20341 case eeSCRIPT13:
20342 case eeSCRIPT14:
20343 case eeSCRIPT15:
20344 case eeSCRIPT16:
20345 case eeSCRIPT17:
20346 case eeSCRIPT18:
20347 case eeSCRIPT19:
20348 case eeSCRIPT20:
20349 {
20350 if ( !get_bit(quest_rules, qr_SCRIPT_FRIENDLY_ENEMY_TYPES) )
20351 {
20352 e = new eScript((zfix)x,(zfix)y,id,clk);
20353 break;
20354 }
20355 else return 0;
20356 }
20357
20358 case eeFFRIENDLY01:
20359 case eeFFRIENDLY02:
20360 case eeFFRIENDLY03:
20361 case eeFFRIENDLY04:
20362 case eeFFRIENDLY05:
20363 case eeFFRIENDLY06:
20364 case eeFFRIENDLY07:
20365 case eeFFRIENDLY08:
20366 case eeFFRIENDLY09:
20367 case eeFFRIENDLY10:
20368 {
20369 if ( !get_bit(quest_rules, qr_SCRIPT_FRIENDLY_ENEMY_TYPES) )
20370 {
20371 e = new eFriendly((zfix)x,(zfix)y,id,clk); break;
20372 }
20373 else return 0;
20374
20375 }
20376
20377 case eeSPINTILE:
20378 e = new eSpinTile((zfix)x,(zfix)y,id,clk);
20379 break;
20380
20381 // and these enemies use the misc10/misc2 value
20382 case eeROCK:
20383 {
20384 switch(guysbuf[id&0xFFF].misc10)
20385 {
20386 case 1:
20387 e = new eBoulder((zfix)x,(zfix)y,id,clk);
20388 break;
20389
20390 case 0:
20391 default:
20392 e = new eRock((zfix)x,(zfix)y,id,clk);
20393 break;
20394 }
20395
20396 break;
20397 }
20398
20399 case eeTRAP:
20400 {
20401 switch(guysbuf[id&0xFFF].misc2)
20402 {
20403 case 1:
20404 e = new eTrap2((zfix)x,(zfix)y,id,clk);
20405 break;
20406
20407 case 0:
20408 default:
20409 e = new eTrap((zfix)x,(zfix)y,id,clk);
20410 break;
20411 }
20412
20413 break;
20414 }
20415
20416 case eeDONGO:
20417 {
20418 switch(guysbuf[id&0xFFF].misc10)
20419 {
20420 case 1:
20421 e = new eDodongo2((zfix)x,(zfix)y,id,clk);
20422 break;
20423
20424 case 0:
20425 default:
20426 e = new eDodongo((zfix)x,(zfix)y,id,clk);
20427 break;
20428 }
20429
20430 break;
20431 }
20432
20433 case eeDIG:
20434 {
20435 switch(guysbuf[id&0xFFF].misc10)
20436 {
20437 case 1:
20438 e = new eLilDig((zfix)x,(zfix)y,id,clk);
20439 break;
20440
20441 case 0:
20442 default:
20443 e = new eBigDig((zfix)x,(zfix)y,id,clk);
20444 break;
20445 }
20446
20447 break;
20448 }
20449
20450 case eePATRA:
20451 {
20452 switch(guysbuf[id&0xFFF].misc10)
20453 {
20454 case 1:
20455 if (get_bit(quest_rules,qr_HARDCODED_BS_PATRA))
20456 {
20457 e = new ePatraBS((zfix)x,(zfix)y,id,clk);
20458 break;
20459 }
20460 [[fallthrough]];
20461 case 0:
20462 default:
20463 e = new ePatra((zfix)x,(zfix)y,id,clk);
20464 break;
20465 }
20466
20467 break;
20468 }
20469
20470 case eeGUY:
20471 {
20472 switch(guysbuf[id&0xFFF].misc10)
20473 {
20474 case 1:
20475 e = new eTrigger((zfix)x,(zfix)y,id,clk);
20476 break;
20477
20478 case 0:
20479 default:
20480 e = new eNPC((zfix)x,(zfix)y,id,clk);
20481 break;
20482 }
20483
20484 break;
20485 }
20486
20487 case eeNONE:
20488 if(guysbuf[id&0xFFF].misc10 ==1)
20489 {
20490 e = new eTrigger((zfix)x,(zfix)y,id,clk);
20491 break;
20492 break;
20493 }
20494 [[fallthrough]];
20495 default:
20496
20497 return 0;
20498 }
20499
20500 12 ret++; // Made one enemy.
20501
20502
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 if(z && canfall(id))
20503 {
20504 e->z = (zfix)z;
20505 }
20506
20507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 ((enemy*)e)->ceiling = (z && canfall(id));
20508
20509
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if(!guys.add(e))
20510 {
20511 return 0;
20512 }
20513
20514 // add segments of segmented enemies
20515 12 int32_t c=0;
20516
20517
1/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
12 switch(guysbuf[id&0xFFF].family)
20518 {
20519 case eeMOLD:
20520 {
20521 byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
20522 id &= 0xFFF;
20523
20524 for(int32_t i=0; i<zc_max(1,zc_min(254,guysbuf[id].misc1)); i++)
20525 {
20526 //christ this is messy -DD
20527 int32_t segclk = -i*((int32_t)(8.0/(zslongToFix(guysbuf[id&0xFFF].step*100))));
20528
20529 if(!guys.add(new esMoldorm((zfix)x,(zfix)y,id+0x1000,segclk)))
20530 {
20531 al_trace("Moldorm segment %d could not be created!\n",i+1);
20532
20533 for(int32_t j=0; j<i+1; j++)
20534 guys.del(guys.Count()-1);
20535
20536 return 0;
20537 }
20538
20539 if(i>0)
20540 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
20541
20542 ret++;
20543 }
20544
20545 break;
20546 }
20547
20548 case eeLANM:
20549 {
20550 id &= 0xFFF;
20551 int32_t shft = guysbuf[id].misc2;
20552 byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
20553
20554 if(!guys.add(new esLanmola((zfix)x,(zfix)y,id+0x1000,0)))
20555 {
20556 al_trace("Lanmola segment 1 could not be created!\n");
20557 guys.del(guys.Count()-1);
20558 return 0;
20559 }
20560
20561 ret++;
20562
20563 for(int32_t i=1; i<zc_max(1,zc_min(253,guysbuf[id&0xFFF].misc1)); i++)
20564 {
20565 if(!guys.add(new esLanmola((zfix)x,(zfix)y,id+0x2000,-(i<<shft))))
20566 {
20567 al_trace("Lanmola segment %d could not be created!\n",i+1);
20568
20569 for(int32_t j=0; j<i+1; j++)
20570 guys.del(guys.Count()-1);
20571
20572 return 0;
20573 }
20574
20575 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
20576 ret++;
20577 }
20578 }
20579 break;
20580
20581 case eeMANHAN:
20582 id &= 0xFFF;
20583
20584 for(int32_t i=0; i<((!(guysbuf[id].misc2))?4:8); i++)
20585 {
20586 if(!guys.add(new esManhandla((zfix)x,(zfix)y,id+0x1000,i)))
20587 {
20588 al_trace("Manhandla head %d could not be created!\n",i+1);
20589
20590 for(int32_t j=0; j<i+1; j++)
20591 {
20592 guys.del(guys.Count()-1);
20593 }
20594
20595 return 0;
20596 }
20597
20598 ret++;
20599 ((enemy*)guys.spr(guys.Count()-1))->frate=guysbuf[id].misc1;
20600 }
20601
20602 break;
20603
20604 case eeGLEEOK:
20605 {
20606 id &= 0xFFF;
20607
20608 for(int32_t i=0; i<zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)); i++)
20609 {
20610 if(!guys.add(new esGleeok((zfix)x,(zfix)y,id+0x1000,c, e)))
20611 {
20612 al_trace("Gleeok head %d could not be created!\n",i+1);
20613
20614 for(int32_t j=0; j<i+1; j++)
20615 {
20616 guys.del(guys.Count()-1);
20617 }
20618
20619 return false;
20620 }
20621
20622 c-=guysbuf[id].misc4;
20623 ret++;
20624 }
20625 }
20626 break;
20627
20628
20629 case eePATRA:
20630 {
20631 id &= 0xFFF;
20632 int32_t outeyes = 0;
20633
20634 for(int32_t i=0; i<zc_min(254,guysbuf[id&0xFFF].misc1); i++)
20635 {
20636 if(!((guysbuf[id].misc10&&get_bit(quest_rules,qr_HARDCODED_BS_PATRA))?guys.add(new esPatraBS((zfix)x,(zfix)y,id+0x1000,i,e)):guys.add(new esPatra((zfix)x,(zfix)y,id+0x1000,i,e))))
20637 {
20638 al_trace("Patra outer eye %d could not be created!\n",i+1);
20639
20640 for(int32_t j=0; j<i+1; j++)
20641 guys.del(guys.Count()-1);
20642
20643 return 0;
20644 }
20645 else
20646 outeyes++;
20647
20648 ret++;
20649 }
20650
20651 for(int32_t i=0; i<zc_min(254,guysbuf[id&0xFFF].misc2); i++)
20652 {
20653 if(!guys.add(new esPatra((zfix)x,(zfix)y,id+0x1000,i,e)))
20654 {
20655 al_trace("Patra inner eye %d could not be created!\n",i+1);
20656
20657 for(int32_t j=0; j<i+1+zc_min(254,outeyes); j++)
20658 guys.del(guys.Count()-1);
20659
20660 return 0;
20661 }
20662
20663 ret++;
20664 }
20665
20666 break;
20667 }
20668 }
20669
20670 12 return ret;
20671 12 }
20672
20673 bool isjumper(int32_t id)
20674 {
20675 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
20676 {
20677 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "isjumper()");
20678 return false;
20679 }
20680 switch(guysbuf[id&0xFFF].family)
20681 {
20682 case eeROCK:
20683 case eeTEK:
20684 return true;
20685
20686 case eeWALK:
20687 if(guysbuf[id&0xFFF].misc9==e9tVIRE || guysbuf[id&0xFFF].misc9==e9tPOLSVOICE) return true;
20688 }
20689
20690 return false;
20691 }
20692
20693
20694 bool isfixedtogrid(int32_t id)
20695 {
20696 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
20697 {
20698 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "isfixedtogrid()");
20699 return false;
20700 }
20701 switch(guysbuf[id&0xFFF].family)
20702 {
20703 case eeWALK:
20704 case eeLEV:
20705 case eeZORA:
20706 case eeDONGO:
20707 case eeGANON:
20708 case eeROCK:
20709 case eeGLEEOK:
20710 case eeAQUA:
20711 case eeLANM:
20712 return true;
20713 }
20714
20715 return false;
20716 }
20717
20718 // Can't fall, can have Z value.
20719 5092 bool isflier(int32_t id)
20720 {
20721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5092 times.
5092 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
20722 {
20723 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "isflier()");
20724 return false;
20725 }
20726
1/2
✓ Branch 0 taken 5092 times.
✗ Branch 1 not taken.
5092 switch(guysbuf[id&0xFFF].family) //id&0x0FFF)
20727 {
20728 case eePEAHAT:
20729 case eeKEESE:
20730 case eePATRA:
20731 case eeFAIRY:
20732 case eeGHINI:
20733
20734 // Could theoretically have their Z set by a script
20735 case eeFIRE:
20736 return true;
20737 break;
20738 }
20739
20740 5092 return false;
20741 5092 }
20742
20743 // Can't have Z position
20744 bool never_in_air(int32_t id)
20745 {
20746 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
20747 {
20748 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "never_in_air()");
20749 return false;
20750 }
20751 switch(guysbuf[id&0xFFF].family)
20752 {
20753 case eeMANHAN:
20754 case eeMOLD:
20755 case eeLANM:
20756 case eeGLEEOK:
20757 case eeZORA:
20758 case eeLEV:
20759 case eeAQUA:
20760 case eeROCK:
20761 case eeGANON:
20762 case eeTRAP:
20763 case eePROJECTILE:
20764 case eeSPINTILE:
20765 return true;
20766 }
20767
20768 return false;
20769 }
20770
20771 bool canfall(int32_t id)
20772 {
20773 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
20774 {
20775 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "canfall()");
20776 return false;
20777 }
20778 switch(guysbuf[id&0xFFF].family)
20779 {
20780 case eeGUY:
20781 {
20782 if(id < eOCTO1S)
20783 return false;
20784
20785 switch(guysbuf[id&0xFFF].misc10)
20786 {
20787 case 1:
20788 case 2:
20789 return true;
20790
20791 case 0:
20792 case 3:
20793 default:
20794 return false;
20795 }
20796
20797 case eeGHOMA:
20798 case eeDIG:
20799 return false;
20800 }
20801 }
20802
20803
20804 return !never_in_air(id) && !isflier(id) && !isjumper(id);
20805 }
20806
20807 3671 bool enemy::enemycanfall(int32_t id, bool checkgrav)
20808 {
20809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3671 times.
3671 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
20810 {
20811 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "enemycanfall()");
20812 return false;
20813 }
20814 //Z_scripterrlog("canfall family is %d:\n", family);
20815 //Z_scripterrlog("canfall gravity is %s:\n", moveflags & FLAG_OBEYS_GRAV ? "true" : "false");
20816 //if ( family == eeFIRE && id >= eSTART )
20817 //{
20818 // Z_scripterrlog("eeFire\n");
20819 // return moveflags & FLAG_OBEYS_GRAV; //'Other' enemy class, used by scripts. -Z
20820 //}
20821
20822 //In ZQ, eeFIRE is Other(floating) and eeOTHER is 'other'.
20823
20824
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 2291 times.
✓ Branch 2 taken 1380 times.
3671 switch(guysbuf[id&0xFFF].family)
20825 {
20826 case eeGUY:
20827 {
20828
1/2
✓ Branch 0 taken 1380 times.
✗ Branch 1 not taken.
1380 if(id < eOCTO1S) //screen guys and fires that aren't real enemies, and never fall
20829 1380 return false;
20830
20831 switch(guysbuf[id&0xFFF].misc10) //I'm unsure what these specify off-hand. Needs better comments. -Z
20832 {
20833 case 1:
20834 case 2:
20835 return true;
20836
20837 case 0:
20838 case 3:
20839 default:
20840 return false;
20841 }
20842
20843 case eeGHOMA:
20844 case eeDIG:
20845 return false;
20846 }
20847 }
20848
20849
1/2
✓ Branch 0 taken 2291 times.
✗ Branch 1 not taken.
2291 if(!checkgrav) return true;
20850 2291 return (moveflags & FLAG_OBEYS_GRAV);
20851
20852 // if ( isflier(id) || isjumper(id) || never_in_air(id) )
20853 // {
20854 // if ( moveflags & FLAG_OBEYS_GRAV ) return true;
20855 // else return false;
20856 // }
20857 // else
20858 // {
20859 // return (moveflags & FLAG_OBEYS_GRAV);
20860 // }
20861 //return !never_in_air(id) && !isflier(id) && !isjumper(id);
20862 3671 }
20863
20864 1 void addfires()
20865 {
20866
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(!get_bit(quest_rules,qr_NOGUYFIRES))
20867 {
20868 1 int32_t bs = get_bit(quest_rules,qr_BSZELDA);
20869 1 addguy(bs? 64: 72,64,gFIRE,-17,false);
20870 1 addguy(bs?176:168,64,gFIRE,-18,false);
20871 1 }
20872 1 }
20873
20874 9 void loadguys()
20875 {
20876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(loaded_guys)
20877 return;
20878
20879 9 loaded_guys=true;
20880
20881 9 byte Guy=0;
20882 // When in caves/item rooms, use mSPECIALITEM and ipONETIME2
20883 // Else use mITEM and ipONETIME
20884 9 int32_t mf = (currscr>=128) ? mSPECIALITEM : mITEM;
20885 9 int32_t onetime = (currscr>=128) ? ipONETIME2 : ipONETIME;
20886
20887 9 repaircharge=0;
20888 9 adjustmagic=false;
20889 9 learnslash=false;
20890
20891
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
36 for(int32_t i=0; i<3; i++)
20892 {
20893 27 prices[i]=0;
20894 27 }
20895
20896 9 hasitem=0;
20897
20898
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
9 if(currscr>=128 && DMaps[currdmap].flags&dmfGUYCAVES)
20899 {
20900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(DMaps[currdmap].flags&dmfCAVES)
20901 {
20902 1 Guy=tmpscr[1].guy;
20903 1 }
20904 1 }
20905 else
20906 {
20907 8 Guy=tmpscr->guy;
20908
20909
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if(currscr < 0x80 && (DMaps[currdmap].flags&dmfVIEWMAP))
20910 game->maps[(currmap*MAPSCRSNORMAL)+currscr] |= mVISITED; // mark as visited
20911 }
20912
20913 // The Guy appears if 'Hero is in cave' equals 'Guy is in cave'.
20914
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1 times.
9 if(Guy && ((currscr>=128) == !!(DMaps[currdmap].flags&dmfGUYCAVES)))
20915 {
20916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(tmpscr->room==rZELDA)
20917 {
20918 addguy(120,72,Guy,-15,true);
20919 guys.spr(0)->hxofs=1000;
20920 addenemy(128,96,eFIRE,-15);
20921 addenemy(112,96,eFIRE,-15);
20922 addenemy(96,120,eFIRE,-15);
20923 addenemy(144,120,eFIRE,-15);
20924 return;
20925 }
20926
20927
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(Guy!=gFAIRY || !get_bit(quest_rules,qr_NOFAIRYGUYFIRES))
20928 1 addfires();
20929
20930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(currscr>=128)
20931
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(getmapflag() && !(tmpscr->flags9&fBELOWRETURN))
20932 Guy=0;
20933
20934
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 switch(tmpscr->room)
20935 {
20936 case rSP_ITEM:
20937 case rGRUMBLE:
20938 case rBOMBS:
20939 case rARROWS:
20940 case rSWINDLE:
20941 case rMUPGRADE:
20942 case rLEARNSLASH:
20943 case rTAKEONE:
20944 if((get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag((currscr < 128) ? mITEM : mSPECIALITEM)) || (!get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag() && !(tmpscr->flags9&fBELOWRETURN))) //get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)
20945 Guy=0;
20946
20947 break;
20948
20949 case rREPAIR:
20950 if (get_bit(quest_rules, qr_OLD_DOORREPAIR)) break;
20951 if((get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag((currscr < 128) ? mITEM : mSPECIALITEM)) || (!get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag() && !(tmpscr->flags9&fBELOWRETURN))) //get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)
20952 Guy=0;
20953
20954 break;
20955 case rRP_HC:
20956 if (get_bit(quest_rules, qr_OLD_POTION_OR_HC)) break;
20957 if((get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag((currscr < 128) ? mITEM : mSPECIALITEM)) || (!get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag() && !(tmpscr->flags9&fBELOWRETURN))) //get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)
20958 Guy=0;
20959
20960 break;
20961 case rMONEY:
20962 if (get_bit(quest_rules, qr_OLD_SECRETMONEY)) break;
20963 if((get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag((currscr < 128) ? mITEM : mSPECIALITEM)) || (!get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW) && getmapflag() && !(tmpscr->flags9&fBELOWRETURN))) //get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)
20964 Guy=0;
20965
20966 break;
20967
20968 case rTRIFORCE:
20969 {
20970 int32_t tc = TriforceCount();
20971
20972 if(get_bit(quest_rules,qr_4TRI))
20973 {
20974 if((get_bit(quest_rules,qr_3TRI) && tc>=3) || tc>=4)
20975 Guy=0;
20976 }
20977 else
20978 {
20979 if((get_bit(quest_rules,qr_3TRI) && tc>=6) || tc>=8)
20980 Guy=0;
20981 }
20982 }
20983 break;
20984 }
20985
20986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(Guy)
20987 {
20988
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if(Guy!=gFAIRY || !get_bit(quest_rules,qr_NOFAIRYGUYFIRES))
20989 1 blockpath=true;
20990
20991
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(currscr<128)
20992 sfx(WAV_SCALE);
20993
20994
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 addguy(120,64,Guy, (dlevel||BSZ)?-15:startguy[zc_oldrand()&7], true);
20995 1 Hero.Freeze();
20996 1 }
20997 1 }
20998
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 else if(Guy==gFAIRY) // The only Guy that somewhat ignores the "Guys In Caves Only" DMap flag
20999 {
21000 sfx(WAV_SCALE);
21001 addguy(120,62,gFAIRY,-14,false);
21002 }
21003
21004 9 loaditem();
21005
21006 // Collecting a rupee in a '10 Rupees' screen sets the mITEM screen state if
21007 // it doesn't appear in a Cave/Item Cellar, and the mSPECIALITEM screen state if it does.
21008
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 if(tmpscr->room==r10RUPIES && !getmapflag(mf))
21009 {
21010 //setmapflag();
21011 for(int32_t i=0; i<10; i++)
21012 additem(ten_rupies_x[i],ten_rupies_y[i],0,ipBIGRANGE+onetime,-14);
21013 }
21014 9 }
21015
21016 9 void loaditem()
21017 {
21018 9 byte Item = 0;
21019
21020
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if(currscr<128)
21021 {
21022 8 Item=tmpscr->item;
21023
21024
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if((!getmapflag(mITEM) || (tmpscr->flags9&fITEMRETURN)) && (tmpscr->hasitem != 0))
21025 {
21026 if(tmpscr->flags8&fSECRETITEM)
21027 hasitem=8;
21028 else if(tmpscr->flags&fITEM)
21029 hasitem=1;
21030 else if(tmpscr->enemyflags&efCARRYITEM)
21031 hasitem=4; // Will be set to 2 by roaming_item
21032 else
21033 items.add(new item((zfix)tmpscr->itemx,
21034 (tmpscr->flags7&fITEMFALLS && isSideViewGravity()) ? (zfix)-170 : (zfix)tmpscr->itemy+(get_bit(quest_rules, qr_NOITEMOFFSET)?0:1),
21035 (tmpscr->flags7&fITEMFALLS && !(isSideViewGravity())) ? (zfix)170 : (zfix)0,
21036 Item,ipONETIME|ipBIGRANGE|((itemsbuf[Item].family==itype_triforcepiece ||
21037 (tmpscr->flags3&fHOLDITEM)) ? ipHOLDUP : 0) | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0),0));
21038 }
21039 8 }
21040
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if(!(DMaps[currdmap].flags&dmfCAVES))
21041 {
21042 if((!getmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM) || (tmpscr[1].flags9&fBELOWRETURN)) && tmpscr[1].room==rSP_ITEM
21043 && (currscr==128 || !get_bit(quest_rules,qr_ITEMSINPASSAGEWAYS)))
21044 {
21045 Item=tmpscr[1].catchall;
21046
21047 if(Item)
21048 items.add(new item((zfix)tmpscr->itemx,
21049 (tmpscr->flags7&fITEMFALLS && isSideViewGravity()) ? (zfix)-170 : (zfix)tmpscr->itemy+(get_bit(quest_rules, qr_NOITEMOFFSET)?0:1),
21050 (tmpscr->flags7&fITEMFALLS && !(isSideViewGravity())) ? (zfix)170 : (zfix)0,
21051 Item,ipONETIME2|ipBIGRANGE|ipHOLDUP | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0),0));
21052 }
21053 }
21054 9 }
21055
21056 void never_return(int32_t index)
21057 {
21058 if(!get_bit(quest_rules,qr_KILLALL))
21059 goto doit;
21060
21061 for(int32_t i=0; i<guys.Count(); i++)
21062 if(((((enemy*)guys.spr(i))->d->flags)&guy_neverret) && i!=index)
21063 {
21064 goto dontdoit;
21065 }
21066
21067 doit:
21068 setmapflag(mNEVERRET);
21069 dontdoit:
21070 return;
21071 }
21072
21073 8 bool slowguy(int32_t id)
21074 {
21075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
21076 {
21077 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "slowguy()");
21078 return false;
21079 }
21080 //return (guysbuf[id].step<100);
21081
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 switch(id)
21082 {
21083 case eOCTO1S:
21084 case eOCTO2S:
21085 case eOCTO1F:
21086 case eOCTO2F:
21087 case eLEV1:
21088 case eLEV2:
21089 case eROCK:
21090 case eBOULDER:
21091 4 return true;
21092 }
21093
21094 4 return false;
21095 8 }
21096
21097 12 bool ok2add(int32_t id)
21098 {
21099
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if( ((unsigned)(id&0xFFF)) > MAXGUYS || id <= 0)
21100 {
21101 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "oktoadd()");
21102 return false;
21103 }
21104
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 if(getmapflag(mNEVERRET) && (guysbuf[id].flags & guy_neverret))
21105 return false;
21106
21107
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 switch(guysbuf[id].family)
21108 {
21109 // I added a special case for shooters because having traps on the same screen
21110 // was preventing them from spawning due to TMPNORET. This means they will
21111 // never stay dead, though, so it may not be the best solution. - Saf
21112 case eePROJECTILE:
21113 return true;
21114
21115
21116 case eeDIG:
21117 {
21118 switch(guysbuf[id].misc10)
21119 {
21120 case 1:
21121 if(!get_bit(quest_rules,qr_NOTMPNORET))
21122 return !getmapflag(mTMPNORET);
21123
21124 return true;
21125
21126 case 0:
21127 default:
21128 return true;
21129 }
21130 }
21131 case eeGANON:
21132 case eeTRAP:
21133 if ((guysbuf[id].family == eeGANON && !get_bit(quest_rules, qr_CAN_PLACE_GANON))
21134 || (guysbuf[id].family == eeTRAP && !get_bit(quest_rules, qr_CAN_PLACE_TRAPS))) return false;
21135 [[fallthrough]];
21136 default:
21137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (guysbuf[id].flags2&guy_ignoretmpnr) return true;
21138 12 break;
21139 }
21140
21141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(!get_bit(quest_rules,qr_NOTMPNORET))
21142 12 return !getmapflag(mTMPNORET);
21143
21144 return true;
21145 12 }
21146
21147 void activate_fireball_statue(int32_t pos)
21148 {
21149 if(!(tmpscr->enemyflags&efFIREBALLS) || statueID<0)
21150 {
21151 return;
21152 }
21153
21154 int32_t cx=-1000, cy=-1000;
21155 int32_t x = (pos&15)<<4;
21156 int32_t y = pos&0xF0;
21157
21158 int32_t ctype = combobuf[MAPCOMBO(x,y)].type;
21159
21160 if(!isfixedtogrid(statueID))
21161 {
21162 if(ctype==cL_STATUE)
21163 {
21164 cx=x+4;
21165 cy=y+7;
21166 }
21167 else if(ctype==cR_STATUE)
21168 {
21169 cx=x-8;
21170 cy=y-1;
21171 }
21172 else if(ctype==cC_STATUE)
21173 {
21174 cx=x;
21175 cy=y;
21176 }
21177 }
21178 else if(ctype==cL_STATUE || ctype==cR_STATUE || ctype==cC_STATUE)
21179 {
21180 cx=x;
21181 cy=y;
21182 }
21183
21184 if(cx!=-1000) // No point creating it if this is false
21185 {
21186 for(int32_t j=0; j<guys.Count(); j++)
21187 {
21188 if((int32_t(guys.spr(j)->x)==cx)&&(int32_t(guys.spr(j)->y)==cy))
21189 {
21190 if((guys.spr(j)->id&0xFFF) == statueID) // There's already a matching enemy here!
21191 return; // No point deleting it. A script might be toying with it in some way.
21192 else
21193 guys.del(j);
21194 }
21195 }
21196
21197 addenemy(cx, cy, statueID, !isfixedtogrid(statueID) ? 24 : 0);
21198 }
21199 }
21200
21201 9 void activate_fireball_statues()
21202 {
21203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(!(tmpscr->enemyflags&efFIREBALLS))
21204 {
21205 9 return;
21206 }
21207
21208 for(int32_t i=0; i<176; i++)
21209 {
21210 activate_fireball_statue(i);
21211 }
21212 9 }
21213
21214 9 void load_default_enemies()
21215 {
21216 9 wallm_load_clk=frame-80;
21217 9 int32_t Id=0;
21218
21219
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(tmpscr->enemyflags&efZORA)
21220 {
21221 if(zoraID>=0)
21222 addenemy(-16, -16, zoraID, 0);
21223 }
21224
21225
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(tmpscr->enemyflags&efTRAP4)
21226 {
21227 if(cornerTrapID>=0)
21228 {
21229 addenemy(32, 32, cornerTrapID, -14);
21230 addenemy(208, 32, cornerTrapID, -14);
21231 addenemy(32, 128, cornerTrapID, -14);
21232 addenemy(208, 128, cornerTrapID, -14);
21233 }
21234 }
21235
21236
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 9 times.
108 for(int32_t y=0; y<176; y+=16)
21237 {
21238
2/2
✓ Branch 0 taken 1584 times.
✓ Branch 1 taken 99 times.
1683 for(int32_t x=0; x<256; x+=16)
21239 {
21240 1584 int32_t ctype = combobuf[MAPCOMBO(x,y)].type;
21241 1584 int32_t cflag = MAPFLAG(x, y);
21242 1584 int32_t cflag_i = MAPCOMBOFLAG(x, y);
21243
21244
3/6
✓ Branch 0 taken 1584 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1584 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1584 times.
1584 if(ctype==cTRAP_H || cflag==mfTRAP_H || cflag_i==mfTRAP_H)
21245 {
21246 if(trapLOSHorizontalID>=0)
21247 addenemy(x, y, trapLOSHorizontalID, -14);
21248 }
21249
3/6
✓ Branch 0 taken 1584 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1584 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1584 times.
1584 else if(ctype==cTRAP_V || cflag==mfTRAP_V || cflag_i==mfTRAP_V)
21250 {
21251 if(trapLOSVerticalID>=0)
21252 addenemy(x, y, trapLOSVerticalID, -14);
21253 }
21254
3/6
✓ Branch 0 taken 1584 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1584 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1584 times.
1584 else if(ctype==cTRAP_4 || cflag==mfTRAP_4 || cflag_i==mfTRAP_4)
21255 {
21256 if(trapLOS4WayID>=0)
21257 {
21258 if(addenemy(x, y, trapLOS4WayID, -14))
21259 guys.spr(guys.Count()-1)->dummy_int[1]=2;
21260 }
21261 }
21262
21263
3/6
✓ Branch 0 taken 1584 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1584 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1584 times.
1584 else if(ctype==cTRAP_LR || cflag==mfTRAP_LR || cflag_i==mfTRAP_LR)
21264 {
21265 if(trapConstantHorizontalID>=0)
21266 addenemy(x, y, trapConstantHorizontalID, -14);
21267 }
21268
3/6
✓ Branch 0 taken 1584 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1584 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1584 times.
1584 else if(ctype==cTRAP_UD || cflag==mfTRAP_UD || cflag_i==mfTRAP_UD)
21269 {
21270 if(trapConstantVerticalID>=0)
21271 addenemy(x, y, trapConstantVerticalID, -14);
21272 }
21273
21274
1/2
✓ Branch 0 taken 1584 times.
✗ Branch 1 not taken.
1584 if(ctype==cSPINTILE1)
21275 {
21276 // Awaken spinning tile
21277 awaken_spinning_tile(tmpscr,COMBOPOS(x,y));
21278 }
21279 1584 }
21280 99 }
21281
21282
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(tmpscr->enemyflags&efTRAP2)
21283 {
21284 if(centerTrapID>=-1)
21285 {
21286 if(addenemy(64, 80, centerTrapID, -14))
21287 guys.spr(guys.Count()-1)->dummy_int[1]=1;
21288
21289 if(addenemy(176, 80, centerTrapID, -14))
21290 guys.spr(guys.Count()-1)->dummy_int[1]=1;
21291 }
21292 }
21293
21294
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(tmpscr->enemyflags&efROCKS)
21295 {
21296 if(rockID>=0)
21297 {
21298 addenemy(zc_oldrand()&0xF0, 0, rockID, 0);
21299 addenemy(zc_oldrand()&0xF0, 0, rockID, 0);
21300 addenemy(zc_oldrand()&0xF0, 0, rockID, 0);
21301 }
21302 }
21303
21304 9 activate_fireball_statues();
21305 9 }
21306
21307 11088 void update_slope_combopos(int32_t lyr, int32_t pos)
21308 {
21309
2/4
✓ Branch 0 taken 11088 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11088 times.
11088 if(unsigned(lyr) > 6 || unsigned(pos) > 175) return;
21310 11088 mapscr* s = FFCore.tempScreens[lyr];
21311 11088 newcombo const& cmb = combobuf[s->data[pos]];
21312
21313 11088 auto id = (176*lyr)+pos;
21314 11088 auto it = slopes.find(id);
21315
21316 11088 bool wasSlope = it!=slopes.end();
21317 11088 bool isSlope = cmb.type == cSLOPE;
21318
21319
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11088 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11088 if(isSlope && !wasSlope)
21320 {
21321 slopes.try_emplace(id, &(s->data[pos]), nullptr, id, pos);
21322 }
21323
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11088 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11088 else if(wasSlope && !isSlope)
21324 {
21325 slopes.erase(it);
21326 }
21327 11088 }
21328 9 void update_slope_comboposes()
21329 {
21330
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 9 times.
72 for(auto lyr = 0; lyr < 7; ++lyr)
21331 {
21332
2/2
✓ Branch 0 taken 11088 times.
✓ Branch 1 taken 63 times.
11151 for(auto pos = 0; pos < 176; ++pos)
21333 11088 update_slope_combopos(lyr,pos);
21334 63 }
21335 9 }
21336
21337 // Everything that must be done before we change a screen's combo to another combo, or a combo's type to another type.
21338 // There's 2 routines because it's unclear if combobuf or tmpscr->data gets modified. -L
21339 void screen_combo_modify_preroutine(mapscr *s, int32_t pos)
21340 {
21341 delete_fireball_shooter(s, pos);
21342 }
21343
21344 // Everything that must be done after we change a screen's combo to another combo. -L
21345 void screen_combo_modify_postroutine(mapscr *s, int32_t pos)
21346 {
21347 s->valid |= mVALID;
21348 activate_fireball_statue(pos);
21349
21350 if(combobuf[s->data[pos]].type==cSPINTILE1)
21351 {
21352 // Awaken spinning tile
21353 awaken_spinning_tile(s,pos);
21354 }
21355 int32_t lyr = -1;
21356 if(s == tmpscr) lyr = 0;
21357 else for(size_t q = 0; q < 6; ++q)
21358 {
21359 if(s == tmpscr2+q)
21360 {
21361 lyr = q+1;
21362 break;
21363 }
21364 }
21365 if(lyr > -1)
21366 update_slope_combopos(lyr,pos);
21367 }
21368
21369 2944 void screen_ffc_modify_postroutine(word index)
21370 {
21371 2944 ffcdata& ff = tmpscr->ffcs[index];
21372 2944 newcombo const& cmb = combobuf[ff.getData()];
21373
21374 2944 auto id = (176*7)+int32_t(index);
21375 2944 auto it = slopes.find(id);
21376
21377 2944 bool wasSlope = it!=slopes.end();
21378
1/2
✓ Branch 0 taken 2944 times.
✗ Branch 1 not taken.
2944 bool isSlope = cmb.type == cSLOPE && !(ff.flags&ffCHANGER);
21379
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2944 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2944 if(isSlope && !wasSlope)
21380 {
21381 slopes.try_emplace(id, nullptr, &ff, id);
21382 }
21383
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2944 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2944 else if(wasSlope && !isSlope)
21384 {
21385 slopes.erase(it);
21386 }
21387 2944 }
21388
21389 void screen_combo_modify_pre(int32_t cid)
21390 {
21391 for(auto lyr = 0; lyr < 7; ++lyr)
21392 {
21393 mapscr* t = FFCore.tempScreens[lyr];
21394 for(int32_t i = 0; i < 176; i++)
21395 {
21396 if(t->data[i] == cid)
21397 {
21398 screen_combo_modify_preroutine(t,i);
21399 }
21400 }
21401 }
21402 }
21403 void screen_combo_modify_post(int32_t cid)
21404 {
21405 for(auto lyr = 0; lyr < 7; ++lyr)
21406 {
21407 mapscr* t = FFCore.tempScreens[lyr];
21408 for(int32_t i = 0; i < 176; i++)
21409 {
21410 if(t->data[i] == cid)
21411 {
21412 screen_combo_modify_postroutine(t,i);
21413 }
21414 }
21415 }
21416 for(word ind = 0; ind < MAXFFCS; ++ind)
21417 {
21418 if(tmpscr->ffcs[ind].getData() == cid)
21419 screen_ffc_modify_postroutine(ind);
21420 }
21421 }
21422
21423 void awaken_spinning_tile(mapscr *s, int32_t pos)
21424 {
21425 addenemy((pos&15)<<4,pos&0xF0,(s->cset[pos]<<12)+eSPINTILE1,combobuf[s->data[pos]].o_tile+zc_max(1,combobuf[s->data[pos]].frames));
21426 }
21427
21428
21429 // It stands for next_side_pos
21430 30 void nsp(bool random)
21431 // moves sle_x and sle_y to the next position
21432 {
21433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if(random)
21434 {
21435 if(zc_oldrand()%2)
21436 {
21437 sle_x = (zc_oldrand()%2) ? 0 : 240;
21438 sle_y = (zc_oldrand()%10)*16;
21439 }
21440 else
21441 {
21442 sle_y = (zc_oldrand()%2) ? 0 : 160;
21443 sle_x = (zc_oldrand()%15)*16;
21444 }
21445
21446 return;
21447 }
21448
21449
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 11 times.
30 if(sle_x==0)
21450 {
21451
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if(sle_y<160)
21452 10 sle_y+=16;
21453 else
21454 1 sle_x+=16;
21455 11 }
21456
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
19 else if(sle_y==160)
21457 {
21458
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 if(sle_x<240)
21459 14 sle_x+=16;
21460 else
21461 1 sle_y-=16;
21462 15 }
21463
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if(sle_x==240)
21464 {
21465
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(sle_y>0)
21466 4 sle_y-=16;
21467 else
21468 sle_x-=16;
21469 4 }
21470 else if(sle_y==0)
21471 {
21472 if(sle_x>0)
21473 sle_x-=16;
21474 else
21475 sle_y+=16;
21476 }
21477 30 }
21478
21479 5 int32_t next_side_pos(bool random)
21480 // moves sle_x and sle_y to the next available position
21481 // returns the direction the enemy should face
21482 {
21483 bool blocked;
21484 5 int32_t c=0;
21485
21486 5 do
21487 {
21488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 nsp(c>35 ? false : random);
21489
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
35 blocked = _walkflag(sle_x,sle_y,2) || _walkflag(sle_x,sle_y+8,2) ||
21490
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (combo_class_buf[COMBOTYPE(sle_x,sle_y)].block_enemies ||
21491
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 MAPFLAG(sle_x,sle_y) == mfNOENEMY || MAPCOMBOFLAG(sle_x,sle_y)==mfNOENEMY ||
21492
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 MAPFLAG(sle_x,sle_y) == mfNOGROUNDENEMY || MAPCOMBOFLAG(sle_x,sle_y)==mfNOGROUNDENEMY ||
21493 5 iswaterex(MAPCOMBO(sle_x,sle_y), currmap, currscr, -1, sle_x, sle_y, true));
21494
21495
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if(++c>50)
21496 return -1;
21497
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 }
21498 30 while(blocked);
21499
21500 5 int32_t dir=0;
21501
21502
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if(sle_x==0) dir=right;
21503
21504
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(sle_y==0) dir=down;
21505
21506
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if(sle_x==240) dir=left;
21507
21508
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(sle_y==168) dir=up;
21509
21510 5 return dir;
21511 5 }
21512
21513 bool can_side_load(int32_t id)
21514 {
21515 if( ((unsigned)(id&0xFFF)) > MAXGUYS )
21516 {
21517 //zprint2("Invalid enemy ID (%d) passed to %s\n", id, "can_side_load()");
21518 return false;
21519 }
21520 switch(guysbuf[id].family) //id&0x0FFF)
21521 {
21522 //case eTEK1:
21523 //case eTEK2:
21524 //case eTEK3:
21525 //case eLEV1:
21526 //case eLEV2:
21527 //case eLEV3:
21528 //case eRAQUAM:
21529 //case eLAQUAM:
21530 //case eDODONGO:
21531 //case eMANHAN:
21532 //case eGLEEOK1:
21533 //case eGLEEOK2:
21534 //case eGLEEOK3:
21535 //case eGLEEOK4:
21536 //case eDIG1:
21537 //case eDIG3:
21538 //case eGOHMA1:
21539 //case eGOHMA2:
21540 //case eCENT1:
21541 //case eCENT2:
21542 //case ePATRA1:
21543 //case ePATRA2:
21544 //case eGANON:
21545 //case eMANHAN2:
21546 //case eCEILINGM: later
21547 //case eFLOORM: later
21548 //case ePATRABS:
21549 //case ePATRAL2:
21550 //case ePATRAL3:
21551 //case eGLEEOK1F:
21552 //case eGLEEOK2F:
21553 //case eGLEEOK3F:
21554 //case eGLEEOK4F:
21555 //case eDODONGOBS:
21556 //case eDODONGOF:
21557 //case eGOHMA3:
21558 //case eGOHMA4:
21559 //case eSHOOTMAGIC:
21560 //case eSHOOTROCK:
21561 //case eSHOOTSPEAR:
21562 //case eSHOOTSWORD:
21563 //case eSHOOTFLAME:
21564 //case eSHOOTFLAME2:
21565 //case eSHOOTFBALL:
21566 case eeTEK:
21567 case eeLEV:
21568 case eeAQUA:
21569 case eeDONGO:
21570 case eeMANHAN:
21571 case eeGLEEOK:
21572 case eeDIG:
21573 case eeGHOMA:
21574 case eeLANM:
21575 case eePATRA:
21576 case eeGANON:
21577 case eePROJECTILE:
21578 return false;
21579 break;
21580 }
21581
21582 return true;
21583 }
21584
21585 static bool script_sle = false;
21586 static int32_t sle_pattern = 0;
21587 void script_side_load_enemies()
21588 {
21589 if(script_sle || sle_clk) return;
21590 sle_cnt = 0;
21591 while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0)
21592 ++sle_cnt;
21593 script_sle = true;
21594 sle_pattern = tmpscr->pattern;
21595 sle_clk = 0;
21596 }
21597
21598 112 void side_load_enemies()
21599 {
21600
3/4
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 1 times.
112 if(!script_sle && sle_clk==0)
21601 {
21602 1 sle_pattern = tmpscr->pattern;
21603 1 sle_cnt = 0;
21604 1 int32_t guycnt = 0;
21605 1 int16_t s = (currmap<<7)+currscr;
21606 1 bool beenhere=false;
21607 1 bool reload=true;
21608 1 bool unbeatablereload = true;
21609
21610 1 load_default_enemies();
21611
21612
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 for(int32_t i=0; i<6; i++)
21613
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(visited[i]==s)
21614 beenhere=true;
21615
21616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(!beenhere)
21617 {
21618 1 visited[vhead]=s;
21619 1 vhead = (vhead+1)%6;
21620 1 }
21621 else if(game->guys[s]==0)
21622 {
21623 sle_cnt=0;
21624 reload=false;
21625 }
21626
21627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(reload)
21628 {
21629 1 sle_cnt = game->guys[s];
21630
21631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if((get_bit(quest_rules, qr_NO_LEAVE_ONE_ENEMY_ALIVE_TRICK) && !beenhere)
21632
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
1 || sle_cnt==0)
21633 {
21634
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
5 while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0)
21635 4 ++sle_cnt;
21636 1 }
21637
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!beenhere && get_bit(quest_rules, qr_UNBEATABLES_DONT_KEEP_DEAD))
21638 {
21639 for(int32_t i = 0; i<sle_cnt && tmpscr->enemy[i]>0; i++)
21640 {
21641 if (!(guysbuf[tmpscr->enemy[i]].flags & guy_doesntcount))
21642 {
21643 unbeatablereload = false;
21644 }
21645 }
21646 if (unbeatablereload)
21647 {
21648 while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0)
21649 {
21650 ++sle_cnt;
21651 }
21652 }
21653 }
21654 1 }
21655
21656
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if((get_bit(quest_rules,qr_ALWAYSRET)) || (tmpscr->flags3&fENEMIESRETURN))
21657 {
21658 sle_cnt = 0;
21659
21660 while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0)
21661 ++sle_cnt;
21662 }
21663
21664
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for(int32_t i=0; i<sle_cnt; i++)
21665 4 ++guycnt;
21666
21667 1 game->guys[s] = guycnt;
21668 1 }
21669
21670
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 5 times.
112 if((++sle_clk+8)%24 == 0)
21671 {
21672 5 int32_t dir = next_side_pos(sle_pattern==pSIDESR);
21673
21674
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
5 if(dir==-1 || tooclose(sle_x,sle_y,32))
21675 {
21676 1 return;
21677 }
21678
21679 4 int32_t enemy_slot=guys.Count();
21680
21681
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 while(sle_cnt > 0 && !ok2add(tmpscr->enemy[sle_cnt-1]))
21682 sle_cnt--;
21683
21684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(sle_cnt > 0)
21685 {
21686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(addenemy(sle_x,sle_y,tmpscr->enemy[--sle_cnt],0))
21687 {
21688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (((enemy*)guys.spr(enemy_slot))->family != eeTEK)
21689 {
21690 4 guys.spr(enemy_slot)->dir = dir;
21691 4 }
21692 4 }
21693 4 }
21694 4 }
21695
21696
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 1 times.
111 if(sle_cnt<=0)
21697 {
21698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(script_sle)
21699 script_sle = false;
21700 1 else loaded_enemies=true;
21701 1 sle_clk = 0;
21702 1 }
21703 112 }
21704
21705 11 bool is_starting_pos(int32_t i, int32_t x, int32_t y, int32_t t)
21706 {
21707
21708
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if(tmpscr->enemy[i]<1||tmpscr->enemy[i]>=MAXGUYS) //Hackish fix for crash in Waterford.st on screen 0x65 of dmap 0 (map 1).
21709 {
21710 //zprint2("is_starting_pos(), tmpscr->enemy[i] is: %d\n", tmpscr->enemy[i]);
21711 return false; //never 0, never OoB.
21712 }
21713 // No corner enemies
21714
2/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11 if((x==0 || x==240) && (y==0 || y==160))
21715
21716 return false;
21717
21718 //Is a no spawn combo...
21719
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if(MAPFLAG(x+8,y+8)==mfNOENEMYSPAWN || MAPCOMBOFLAG(x+8,y+8)==mfNOENEMYSPAWN)
21720 return false;
21721
21722 // No enemies in dungeon walls
21723
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
11 if(isdungeon() && (x<32 || x>=224 || y<32 || y>=144))
21724 return false;
21725
21726 // Too close
21727
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11 if(tooclose(x,y,40) && t<11)
21728 return false;
21729
21730 // Can't fly onto it?
21731
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11 if(isflier(tmpscr->enemy[i])&&
21732 (flyerblocked(x+8,y+8,spw_floater,guysbuf[tmpscr->enemy[i]])||
21733 (_walkflag(x,y+8,2)&&!get_bit(quest_rules,qr_WALLFLIERS))))
21734 return false;
21735
21736 // Can't jump onto it?
21737 if
21738 (
21739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
15 guysbuf[tmpscr->enemy[i]].family==eeTEK
21740
21741
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
11 &&
21742 (
21743
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 COMBOTYPE(x+8,y+8)==cNOJUMPZONE||
21744
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 COMBOTYPE(x+8,y+8)==cNOENEMY||
21745
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 ispitfall(x+8,y+8)||
21746
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 MAPFLAG(x+8,y+8)==mfNOENEMY||
21747 4 MAPCOMBOFLAG(x+8,y+8)==mfNOENEMY
21748 )
21749 )
21750 {
21751 return false;
21752 }
21753
21754 // Other off-limit combos
21755
5/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 3 times.
18 if((!isflier(tmpscr->enemy[i])&& guysbuf[tmpscr->enemy[i]].family!=eeTEK &&
21756
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 (_walkflag(x,y+8,2) || groundblocked(x+8,y+8,guysbuf[tmpscr->enemy[i]]))) &&
21757 7 guysbuf[tmpscr->enemy[i]].family!=eeZORA)
21758 3 return false;
21759
21760 // Don't ever generate enemies on these combos!
21761
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if(COMBOTYPE(x+8,y+8)==cARMOS||COMBOTYPE(x+8,y+8)==cBSGRAVE)
21762 return false;
21763
21764 //BS Dodongos need at least 2 spaces.
21765
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if((guysbuf[tmpscr->enemy[i]].family==eeDONGO)&&(guysbuf[tmpscr->enemy[i]].misc10==1))
21766 {
21767 if(((x<16) ||_walkflag(x-16,y+8, 2))&&
21768 ((x>224)||_walkflag(x+16,y+8, 2))&&
21769 ((y<16) ||_walkflag(x, y-8, 2))&&
21770 ((y>144)||_walkflag(x, y+24,2)))
21771 {
21772 return false;
21773 }
21774 }
21775
21776 8 return true;
21777 11 }
21778
21779 16 bool is_ceiling_pattern(int32_t i)
21780 {
21781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 return (i==pCEILING || i==pCEILINGR);
21782 }
21783
21784 int32_t placeenemy(int32_t i)
21785 {
21786 std::map<int32_t, int32_t> freeposcache;
21787 int32_t frees = 0;
21788
21789 for(int32_t y=0; y<176; y+=16)
21790 {
21791 for(int32_t x=0; x<256; x+=16)
21792 {
21793 if(is_starting_pos(i,x,y,0))
21794 {
21795 freeposcache[frees++] = (y&0xF0)+(x>>4);
21796 }
21797 }
21798 }
21799
21800 if(frees > 0)
21801 return freeposcache[zc_oldrand()%frees];
21802
21803 return -1;
21804 }
21805
21806 8 void spawnEnemy(int& pos, int& clk, int& x, int& y, int& fastguys, int& i, int& guycnt, int& loadcnt)
21807 {
21808 8 bool placed=false;
21809 8 int32_t t=-1;
21810
21811 // First: enemy combo flags
21812
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 8 times.
96 for(int32_t sy=0; sy<176; sy+=16)
21813 {
21814
2/2
✓ Branch 0 taken 1408 times.
✓ Branch 1 taken 88 times.
1496 for(int32_t sx=0; sx<256; sx+=16)
21815 {
21816 1408 int32_t cflag = MAPFLAG(sx, sy);
21817 1408 int32_t cflag_i = MAPCOMBOFLAG(sx, sy);
21818
21819
2/4
✓ Branch 0 taken 1408 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1408 times.
✗ Branch 3 not taken.
1408 if(((cflag==mfENEMYALL)||(cflag_i==mfENEMYALL)) && (!placed))
21820 {
21821 if(!ok2add(tmpscr->enemy[i]))
21822 {
21823 if (loadcnt < 10 && tmpscr->enemy[i] > 0 && tmpscr->enemy[i] < MAXGUYS) ++loadcnt;
21824 }
21825 else
21826 {
21827 addenemy(sx,
21828 (is_ceiling_pattern(tmpscr->pattern) && isSideViewGravity()) ? -(150+50*guycnt) : sy,
21829 (is_ceiling_pattern(tmpscr->pattern) && !(isSideViewGravity())) ? 150+50*guycnt : 0,tmpscr->enemy[i],-15);
21830
21831 ++guycnt;
21832
21833 placed=true;
21834 goto placed_enemy;
21835 }
21836 }
21837
21838
2/4
✓ Branch 0 taken 1408 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1408 times.
✗ Branch 3 not taken.
1408 else if(((cflag==mfENEMY0+i)||(cflag_i==mfENEMY0+i)) && (!placed))
21839 {
21840 if(!ok2add(tmpscr->enemy[i]))
21841 {
21842 if (loadcnt < 10 && tmpscr->enemy[i] > 0 && tmpscr->enemy[i] < MAXGUYS) ++loadcnt;
21843 }
21844 else
21845 {
21846 addenemy(sx,
21847 (is_ceiling_pattern(tmpscr->pattern) && isSideViewGravity()) ? -(150+50*guycnt) : sy,
21848 (is_ceiling_pattern(tmpscr->pattern) && !(isSideViewGravity())) ? 150+50*guycnt : 0,tmpscr->enemy[i],-15);
21849
21850 ++guycnt;
21851
21852 placed=true;
21853 goto placed_enemy;
21854 }
21855 }
21856 1408 }
21857 88 }
21858
21859 // Next: enemy pattern
21860
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
8 if((tmpscr->pattern==pRANDOM || tmpscr->pattern==pCEILING) && !(isSideViewGravity()) && ((tmpscr->enemy[i]>0&&tmpscr->enemy[i]<MAXGUYS)))
21861 {
21862 8 do
21863 {
21864
21865 // NES positions
21866 11 pos%=9;
21867 11 x=stx[loadside][pos];
21868 11 y=sty[loadside][pos];
21869 11 ++pos;
21870 11 ++t;
21871
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
19 }
21872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 while((t< 20) && !is_starting_pos(i,x,y,t));
21873 8 }
21874
21875
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if(t<0 || t >= 20) // above enemy pattern failed
21876 {
21877 // Final chance: find a random position anywhere onscreen
21878 int32_t randpos = placeenemy(i);
21879
21880 if(randpos>-1)
21881 {
21882 x=(randpos&15)<<4;
21883 y= randpos&0xF0;
21884 }
21885 else // All opportunities failed - abort
21886 {
21887 return;
21888 }
21889 }
21890
21891 {
21892 8 int32_t c=0;
21893 8 c=clk;
21894
21895
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if(!slowguy(tmpscr->enemy[i]))
21896 4 ++fastguys;
21897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 else if(fastguys>0)
21898 c=-15*(i-fastguys+2);
21899 else
21900 4 c=-15*(i+1);
21901
21902
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if(BSZ&&((tmpscr->enemy[i]>0&&tmpscr->enemy[i]<MAXGUYS))) // Hackish fix for crash in Waterford.qst on screen 0x65 of dmap 0 (map 1).
21903 {
21904 // Special case for blue leevers
21905 if(guysbuf[tmpscr->enemy[i]].family==eeLEV && guysbuf[tmpscr->enemy[i]].misc1==1)
21906 c=-15*(i+1);
21907 else
21908 c=-15;
21909 }
21910
21911
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if(!ok2add(tmpscr->enemy[i]))
21912 {
21913 if (loadcnt < 10 && tmpscr->enemy[i] > 0 && tmpscr->enemy[i] < MAXGUYS) ++loadcnt;
21914 }
21915 else
21916 {
21917
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if(((tmpscr->enemy[i]>0||tmpscr->enemy[i]<MAXGUYS))) // Hackish fix for crash in Waterford.qst on screen 0x65 of dmap 0 (map 1).
21918 {
21919
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 addenemy(x,(is_ceiling_pattern(tmpscr->pattern) && isSideViewGravity()) ? -(150+50*guycnt) : y,
21920
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 (is_ceiling_pattern(tmpscr->pattern) && !(isSideViewGravity())) ? 150+50*guycnt : 0,tmpscr->enemy[i],c);
21921
21922 8 ++guycnt;
21923 8 }
21924 }
21925
21926 8 placed=true;
21927 8 } // if(t < 20)
21928
21929 placed_enemy:
21930
21931 // I don't like this, but it seems to work...
21932 static bool foundCarrier;
21933
21934
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if(i==0)
21935 2 foundCarrier=false;
21936
21937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if(placed)
21938 {
21939
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
8 if(i==0 && tmpscr->enemyflags&efLEADER)
21940 {
21941 int32_t index = guys.idFirst(tmpscr->enemy[i],0xFFF);
21942
21943 if(index!=-1)
21944 {
21945 //grab the first segment. Not accurate to how older versions did it, but the way they did it might be incompatible with enemy editor.
21946 if ((((enemy*)guys.spr(index))->family == eeLANM) && !get_bit(quest_rules, qr_NO_LANMOLA_RINGLEADER)) index = guys.idNth(tmpscr->enemy[i], 2, 0xFFF);
21947 if(index!=-1)
21948 {
21949 ((enemy*)guys.spr(index))->leader = true;
21950 }
21951 }
21952 }
21953
21954
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if(!foundCarrier && hasitem&(4|2))
21955 {
21956 int32_t index = guys.idFirst(tmpscr->enemy[i],0xFFF);
21957
21958 if(index!=-1 && (((enemy*)guys.spr(index))->flags&guy_doesntcount)==0)
21959 {
21960 ((enemy*)guys.spr(index))->itemguy = true;
21961 foundCarrier=true;
21962 }
21963 }
21964 8 }
21965 8 }
21966
21967 bool scriptloadenemies()
21968 {
21969 loaded_enemies = true;
21970 if(script_sle || sle_clk) return false;
21971 if(tmpscr->pattern==pNOSPAWN) return false;
21972
21973 if(tmpscr->pattern==pSIDES || tmpscr->pattern==pSIDESR)
21974 {
21975 script_side_load_enemies();
21976 return true;
21977 }
21978
21979 int32_t pos=zc_oldrand()%9;
21980 int32_t clk=-15,x=0,y=0,fastguys=0;
21981 int32_t i=0,guycnt=0;
21982 int32_t loadcnt = 10;
21983
21984 for(; i<loadcnt && tmpscr->enemy[i]>0; i++)
21985 {
21986 spawnEnemy(pos, clk, x, y, fastguys, i, guycnt, loadcnt);
21987
21988 --clk;
21989 }
21990 return true;
21991 }
21992
21993 1875 void loadenemies()
21994 {
21995
3/4
✓ Branch 0 taken 1875 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 1764 times.
1875 if(script_sle || sle_clk)
21996 {
21997 111 side_load_enemies();
21998 111 return;
21999 }
22000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1764 times.
1764 if(tmpscr->pattern==pNOSPAWN) return;
22001
2/2
✓ Branch 0 taken 1755 times.
✓ Branch 1 taken 9 times.
1764 if(loaded_enemies)
22002 1755 return;
22003
22004 // check if it's the dungeon boss and it has been beaten before
22005
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 if(tmpscr->enemyflags&efBOSS && game->lvlitems[dlevel]&liBOSS)
22006 {
22007 loaded_enemies = true;
22008 return;
22009 }
22010
22011
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
9 if(tmpscr->pattern==pSIDES || tmpscr->pattern==pSIDESR)
22012 {
22013 1 side_load_enemies();
22014 1 return;
22015 }
22016
22017 8 loaded_enemies=true;
22018
22019 // do enemies that are always loaded
22020 8 load_default_enemies();
22021
22022 // dungeon basements
22023
22024 static byte dngn_enemy_x[4] = {32,96,144,208};
22025
22026
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if(currscr>=128)
22027 {
22028
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(DMaps[currdmap].flags&dmfCAVES) return;
22029 if ( DMaps[currdmap].flags&dmfNEWCELLARENEMIES )
22030 {
22031 for(int32_t i=0; i<10; i++)
22032 {
22033 if ( tmpscr->enemy[i] )
22034 {
22035 addenemy(dngn_enemy_x[i],96,tmpscr->enemy[i],-14-i);
22036 }
22037 }
22038 }
22039 else
22040 {
22041 for(int32_t i=0; i<4; i++)
22042 addenemy(dngn_enemy_x[i],96,tmpscr->enemy[i]?tmpscr->enemy[i]:(int32_t)eKEESE1,-14-i);
22043 }
22044 return;
22045 }
22046
22047 // check if it's been long enough to reload all enemies
22048
22049 7 int32_t loadcnt = 10;
22050 7 int16_t s = (currmap<<7)+currscr;
22051 7 bool beenhere = false;
22052 7 bool reload = true;
22053 7 bool unbeatablereload = true;
22054
22055
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7 times.
49 for(int32_t i=0; i<6; i++)
22056
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
43 if(visited[i]==s)
22057 1 beenhere = true;
22058
22059
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if(!beenhere) //Okay so this basically checks the last 6 unique screen's you've been in and checks if the current screen is one of them.
22060 {
22061 6 visited[vhead]=s; //If not, it adds it to the array,
22062 6 vhead = (vhead+1)%6; //which overrides one of the others, and then moves onto the next.
22063 6 }
22064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if(game->guys[s]==0) //Then, if you have been here, and the number of enemies left on the screen is 0,
22065 {
22066 1 loadcnt = 0; //It will tell it not to load any enemies,
22067 1 reload = false; //both by setting loadcnt to 0 and making the reload if statement not run.
22068 1 }
22069
22070
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if(reload) //This if statement is only false if this screen is one of the last 6 screens you visited and you left 0 enemies alive.
22071 {
22072 6 loadcnt = game->guys[s]; //Otherwise, if this if statement is true, it will try to load the last amount of enemies you left alive.
22073
22074
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if(loadcnt==0 || //Then, if the number of enemies is 0, that means you left 0 enemies alive on a screen but haven't been there in the past 6 screens.
22075 (get_bit(quest_rules, qr_NO_LEAVE_ONE_ENEMY_ALIVE_TRICK) && !beenhere)) //Alternatively, if you have the quest rule enabled that always respawns all enemies after a period of time, and you haven't been here in 6 screens.
22076 6 loadcnt = 10; //That means all enemies need to be respawned.
22077
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (!beenhere && get_bit(quest_rules, qr_UNBEATABLES_DONT_KEEP_DEAD))
22078 {
22079 for(int32_t i = 0; i<loadcnt && tmpscr->enemy[i]>0; i++)
22080 {
22081 if (!(guysbuf[tmpscr->enemy[i]].flags & guy_doesntcount))
22082 {
22083 unbeatablereload = false;
22084 }
22085 }
22086 if (unbeatablereload)
22087 {
22088 loadcnt = 10;
22089 }
22090 }
22091 6 }
22092
22093
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if((get_bit(quest_rules,qr_ALWAYSRET)) || (tmpscr->flags3&fENEMIESRETURN)) //If enemies always return is enabled quest-wide or for this screen,
22094 loadcnt = 10; //All enemies also need to be respawned.
22095
22096 7 int32_t pos=zc_oldrand()%9; //This sets up a variable for spawnEnemy to edit so as to spawn the enemies pseudo-randomly.
22097 7 int32_t clk=-15,x=0,y=0,fastguys=0; //clk being negative means the enemy is in it's spawn poof.
22098 7 int32_t i=0,guycnt=0; //Lastly, resets guycnt to 0 so spawnEnemy can increment it manually per-enemy.
22099
22100
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 7 times.
15 for(; i<loadcnt && tmpscr->enemy[i]>0; i++)
22101 {
22102 8 spawnEnemy(pos, clk, x, y, fastguys, i, guycnt, loadcnt);
22103
22104 8 --clk; //Each additional enemy spawns with a slightly longer spawn poof than the previous.
22105 8 }
22106
22107 7 game->guys[s] = guycnt;
22108 //} //if(true)
22109 1875 }
22110 void moneysign()
22111 {
22112 additem(48,108,iRupy,ipDUMMY);
22113 // textout(scrollbuf,zfont,"X",64,112,CSET(0)+1);
22114 set_clip_state(pricesdisplaybuf, 0);
22115 textout_ex(pricesdisplaybuf,zfont,"X",64,112,CSET(0)+1,-1);
22116 }
22117
22118 1 void putprices(bool sign)
22119 {
22120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(fadeclk > 0) return;
22121 // refresh what's under the prices
22122 // for(int32_t i=5; i<12; i++)
22123 // putcombo(scrollbuf,i<<4,112,tmpscr->data[112+i],tmpscr->cpage);
22124
22125 1 rectfill(pricesdisplaybuf, 72, 112, pricesdisplaybuf->w-1, pricesdisplaybuf->h-1, 0);
22126 1 int32_t step=32;
22127 1 int32_t x=80;
22128
22129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(prices[2]==0)
22130 {
22131 1 step<<=1;
22132
22133
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(prices[1]==0)
22134 {
22135 1 x=112;
22136 1 }
22137 1 }
22138
22139
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 for(int32_t i=0; i<3; i++)
22140 {
22141 // Kind of stupid, but it works: 100000 is used to indicate that an item
22142 // has a price of zero rather than there being no item.
22143 // 100000 isn't a valid price, so this doesn't cause problems.
22144
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if(prices[i]!=0 && prices[i]<100000)
22145 {
22146 char buf[8];
22147 sprintf(buf,sign?"%+3d":"%3d",prices[i]);
22148
22149 int32_t l=(int32_t)strlen(buf);
22150 set_clip_state(pricesdisplaybuf, 0);
22151 textout_ex(pricesdisplaybuf,zfont,buf,x-(l>3?(l-3)<<3:0),112,CSET(0)+1,-1);
22152 }
22153
22154 3 x+=step;
22155 3 }
22156 1 }
22157
22158 // Setting up special rooms
22159 // Also called when the Letter is used successfully.
22160 1 void setupscreen()
22161 {
22162 1 boughtsomething=false;
22163 1 int32_t t=currscr<128?0:1;
22164 1 word str=tmpscr[t].str;
22165
22166 // Prices are already set to 0 in dowarp()
22167
1/15
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 switch(tmpscr[t].room)
22168 {
22169 case rSP_ITEM: // special item
22170 1 additem(120,89,tmpscr[t].catchall,ipONETIME2+ipHOLDUP+ipCHECK | ((tmpscr->flags8&fITEMSECRET) ? ipSECRETS : 0));
22171 1 break;
22172
22173 case rINFO: // pay for info
22174 {
22175 int32_t count = 0;
22176 int32_t base = 88;
22177 int32_t step = 5;
22178
22179 moneysign();
22180
22181 for(int32_t i=0; i<3; i++)
22182 {
22183 if(QMisc.info[tmpscr[t].catchall].str[i])
22184 {
22185 ++count;
22186 }
22187 else
22188 break;
22189 }
22190
22191 if(count)
22192 {
22193 if(count==1)
22194 {
22195 base = 88+32;
22196 }
22197
22198 if(count==2)
22199 {
22200 step = 6;
22201 }
22202
22203 for(int32_t i=0; i < count; i++)
22204 {
22205 additem((i << step)+base, 89, iRupy, ipMONEY + ipDUMMY);
22206 ((item*)items.spr(items.Count()-1))->PriceIndex = i;
22207 prices[i] = -(QMisc.info[tmpscr[t].catchall].price[i]);
22208 if(prices[i]==0)
22209 prices[i]=100000; // So putprices() knows there's an item here and positions the price correctly
22210 int32_t itemid = current_item_id(itype_wealthmedal);
22211
22212 if(itemid>=0 && prices[i]!=100000)
22213 {
22214 if(itemsbuf[itemid].flags & ITEM_FLAG1)
22215 prices[i]=((prices[i]*itemsbuf[itemid].misc1)/100);
22216 else
22217 prices[i]-=itemsbuf[itemid].misc1;
22218 prices[i]=vbound(prices[i], -99999, 0);
22219 if(prices[i]==0)
22220 prices[i]=100000;
22221 }
22222
22223 if((QMisc.info[tmpscr[t].catchall].price[i])>1 && prices[i]>-1 && prices[i]!=100000)
22224 prices[i]=-1;
22225 }
22226 }
22227
22228 break;
22229 }
22230
22231 case rMONEY: // secret money
22232 additem(120,89,iRupy,ipONETIME+ipDUMMY+ipMONEY);
22233 ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
22234 break;
22235
22236 case rGAMBLE: // gambling
22237 prices[0]=prices[1]=prices[2]=-10;
22238 moneysign();
22239 additem(88,89,iRupy,ipMONEY+ipDUMMY);
22240 ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
22241 additem(120,89,iRupy,ipMONEY+ipDUMMY);
22242 ((item*)items.spr(items.Count()-1))->PriceIndex = 1;
22243 additem(152,89,iRupy,ipMONEY+ipDUMMY);
22244 ((item*)items.spr(items.Count()-1))->PriceIndex = 2;
22245 break;
22246
22247 case rREPAIR: // door repair
22248 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
22249 // }
22250 repaircharge=tmpscr[t].catchall;
22251 break;
22252
22253 case rMUPGRADE: // upgrade magic
22254 adjustmagic=true;
22255 break;
22256
22257 case rLEARNSLASH: // learn slash attack
22258 learnslash=true;
22259 break;
22260
22261 case rRP_HC: // heart container or red potion
22262 additem(88,89,iRPotion,ipONETIME2+ipHOLDUP+ipFADE);
22263 ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
22264 additem(152,89,iHeartC,ipONETIME2+ipHOLDUP+ipFADE);
22265 ((item*)items.spr(items.Count()-1))->PriceIndex = 1;
22266 break;
22267
22268 case rP_SHOP: // potion shop
22269 if(current_item(itype_letter)<i_letter_used)
22270 {
22271 str=0;
22272 break;
22273 }
22274
22275 [[fallthrough]];
22276 case rTAKEONE: // take one
22277 case rSHOP: // shop
22278 {
22279 int32_t count = 0;
22280 int32_t base = 88;
22281 int32_t step = 5;
22282
22283 if(tmpscr[t].room != rTAKEONE)
22284 moneysign();
22285
22286 //count and align the stuff
22287 for(int32_t i=0; i<3; ++i)
22288 {
22289 if(QMisc.shop[tmpscr[t].catchall].hasitem[count] != 0)
22290 {
22291 ++count;
22292 }
22293 else
22294 {
22295 break;
22296 }
22297 }
22298
22299 if(count==1)
22300 {
22301 base = 88+32;
22302 }
22303
22304 if(count==2)
22305 {
22306 step = 6;
22307 }
22308
22309 for(int32_t i=0; i<count; i++)
22310 {
22311 additem((i<<step)+base, 89, QMisc.shop[tmpscr[t].catchall].item[i], ipHOLDUP+ipFADE+(tmpscr[t].room == rTAKEONE ? ipONETIME2 : ipCHECK));
22312 ((item*)items.spr(items.Count()-1))->PriceIndex = i;
22313
22314 if(tmpscr[t].room != rTAKEONE)
22315 {
22316 prices[i] = QMisc.shop[tmpscr[t].catchall].price[i];
22317 if(prices[i]==0)
22318 prices[i]=100000; // So putprices() knows there's an item here and positions the price correctly
22319 int32_t itemid = current_item_id(itype_wealthmedal);
22320
22321 if(itemid>=0 && prices[i]!=100000)
22322 {
22323 if(itemsbuf[itemid].flags & ITEM_FLAG1)
22324 prices[i]=((prices[i]*itemsbuf[itemid].misc1)/100);
22325 else
22326 prices[i]+=itemsbuf[itemid].misc1;
22327 prices[i]=vbound(prices[i], 0, 99999);
22328 if(prices[i]==0)
22329 prices[i]=100000;
22330 }
22331
22332 if((QMisc.shop[tmpscr[t].catchall].price[i])>1 && prices[i]<1)
22333 prices[i]=1;
22334 }
22335 }
22336
22337 break;
22338 }
22339 case rBOTTLESHOP: // bottle shop
22340 {
22341 int32_t count = 0;
22342 int32_t base = 88;
22343 int32_t step = 5;
22344
22345 moneysign();
22346 bottleshoptype const& bst = QMisc.bottle_shop_types[tmpscr[t].catchall];
22347 //count and align the stuff
22348 for(int32_t i=0; i<3; ++i)
22349 {
22350 if(bst.fill[count] != 0)
22351 {
22352 ++count;
22353 }
22354 else
22355 {
22356 break;
22357 }
22358 }
22359
22360 if(count==1)
22361 {
22362 base = 88+32;
22363 }
22364
22365 if(count==2)
22366 {
22367 step = 6;
22368 }
22369
22370 for(int32_t i=0; i<count; i++)
22371 {
22372 adddummyitem((i<<step)+base, 89, /*Use item 0 as a dummy...*/0, ipHOLDUP+ipFADE+ipCHECK);
22373 //{ Setup dummy item
22374 item* curItem = ((item*)items.spr(items.Count()-1));
22375 curItem->PriceIndex = i;
22376 newcombo const& cmb = combobuf[bst.comb[i]];
22377 curItem->o_tile = cmb.o_tile;
22378 curItem->o_cset = bst.cset[i];
22379 curItem->cs = curItem->o_cset;
22380 curItem->tile = cmb.o_tile;
22381 curItem->o_speed = cmb.speed;
22382 curItem->o_delay = 0;
22383 curItem->frames = cmb.frames;
22384 curItem->flip = cmb.flip;
22385 curItem->family = itype_bottlefill; //no pickup w/o empty bottle
22386 curItem->pstring = 0;
22387 curItem->pickup = ipHOLDUP+ipFADE+ipCHECK;
22388 curItem->flash = false;
22389 curItem->twohand = false;
22390 curItem->anim = true;
22391 curItem->hxsz=1;
22392 curItem->hyofs=4;
22393 curItem->hysz=12;
22394 curItem->script=0;
22395 curItem->txsz=1;
22396 curItem->tysz=1;
22397 //}
22398
22399 prices[i] = bst.price[i];
22400 if(prices[i]==0)
22401 prices[i]=100000; // So putprices() knows there's an item here and positions the price correctly
22402 int32_t itemid = current_item_id(itype_wealthmedal);
22403
22404 if(itemid>=0 && prices[i]!=100000)
22405 {
22406 if(itemsbuf[itemid].flags & ITEM_FLAG1)
22407 prices[i]=((prices[i]*itemsbuf[itemid].misc1)/100);
22408 else
22409 prices[i]+=itemsbuf[itemid].misc1;
22410 prices[i]=vbound(prices[i], 0, 99999);
22411 if(prices[i]==0)
22412 prices[i]=100000;
22413 }
22414
22415 if((bst.price[i])>1 && prices[i]<1)
22416 prices[i]=1;
22417 }
22418
22419 break;
22420 }
22421
22422 case rBOMBS: // more bombs
22423 additem(120,89,iRupy,ipDUMMY+ipMONEY);
22424 ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
22425 prices[0]=-tmpscr[t].catchall;
22426 break;
22427
22428 case rARROWS: // more arrows
22429 additem(120,89,iRupy,ipDUMMY+ipMONEY);
22430 ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
22431 prices[0]=-tmpscr[t].catchall;
22432 break;
22433
22434 case rSWINDLE: // leave heart container or money
22435 additem(88,89,iHeartC,ipDUMMY+ipMONEY);
22436 ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
22437 prices[0]=-1;
22438 additem(152,89,iRupy,ipDUMMY+ipMONEY);
22439 ((item*)items.spr(items.Count()-1))->PriceIndex = 1;
22440 prices[1]=-tmpscr[t].catchall;
22441 break;
22442
22443 }
22444
22445
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if(tmpscr[t].room == rBOMBS || tmpscr[t].room == rARROWS)
22446 {
22447 int32_t i = (tmpscr[t].room == rSWINDLE ? 1 : 0);
22448 int32_t itemid = current_item_id(itype_wealthmedal);
22449
22450 if(itemid >= 0)
22451 {
22452 if(itemsbuf[itemid].flags & ITEM_FLAG1)
22453 prices[i]*=(itemsbuf[itemid].misc1/100.0);
22454 else
22455 prices[i]+=itemsbuf[itemid].misc1;
22456 }
22457
22458 if(tmpscr[t].catchall>1 && prices[i]>-1)
22459 prices[i]=-1;
22460 }
22461
22462 1 putprices(false);
22463
22464
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(str)
22465 {
22466 1 donewmsg(str);
22467 1 }
22468 else
22469 {
22470 Hero.unfreeze();
22471 }
22472 1 }
22473
22474 // Increments msgptr and returns the control code argument pointed at.
22475 word grab_next_argument()
22476 {
22477 if(unsigned(msgptr+1)>=MsgStrings[msgstr].s.size()) return 0;
22478 byte val=MsgStrings[msgstr].s[++msgptr]-1;
22479 word ret=val;
22480
22481 // If an argument is succeeded by 255, then it's a three-byte argument -
22482 // between 254 and 65535 (or whatever the maximum actually is)
22483 if((unsigned(msgptr+2)<MsgStrings[msgstr].s.size())
22484 && uint8_t(MsgStrings[msgstr].s[msgptr+1]) == 255)
22485 {
22486 val=MsgStrings[msgstr].s[msgptr+2];
22487 word next=val;
22488 ret += 254*next;
22489 msgptr+=2;
22490 }
22491
22492 return ret;
22493 }
22494
22495 enum
22496 {
22497 MNU_CURSOR_TILE, MNU_CURSOR_CSET,
22498 MNU_CURSOR_WID, MNU_CURSOR_HEI, MNU_CURSOR_FLIP,
22499
22500 MNU_CHOSEN, MNU_TIMER, MNU_CAN_CONFIRM,
22501
22502 MNU_DATA_MAX
22503 };
22504 struct menu_choice
22505 {
22506 int32_t x, y;
22507 int32_t pos;
22508 int32_t upos, dpos, lpos, rpos;
22509 menu_choice() : x(0), y(0), pos(0), upos(0), dpos(0), lpos(0), rpos(0)
22510 {}
22511 menu_choice(int32_t x, int32_t y, int32_t pos, int32_t upos,
22512 int32_t dpos, int32_t lpos, int32_t rpos)
22513 : x(x), y(y), pos(pos), upos(upos), dpos(dpos), lpos(lpos), rpos(rpos)
22514 {}
22515 };
22516 static int32_t msg_menu_data[MNU_DATA_MAX];
22517 static bool do_run_menu = false;
22518 bool do_end_str = false;
22519 static bool wait_advance = false;
22520 11 static std::map<int32_t, menu_choice> menu_options;
22521 21 void clr_msg_data()
22522 {
22523 21 do_end_str = false;
22524 21 wait_advance = false;
22525 21 do_run_menu = false;
22526 21 menu_options.clear();
22527 21 memset(msg_menu_data, 0, sizeof(msg_menu_data));
22528 21 }
22529
22530 static bool doing_name_insert = false;
22531 static char namebuf[9] = {0};
22532 static char* nameptr = NULL;
22533 static int32_t ssc_tile_hei = -1, ssc_tile_hei_buf = -1;
22534 bool runMenuCursor()
22535 {
22536 clear_bitmap(msg_menu_bmp_buf);
22537 if(!menu_options.size())
22538 {
22539 msg_menu_data[MNU_CHOSEN] = 0;
22540 return true; //end menu
22541 }
22542 int32_t pos = msg_menu_data[MNU_CHOSEN];
22543 //If the cursor is at an invalid pos, find the first pos >= 0...
22544 if(menu_options.find(pos) == menu_options.end())
22545 {
22546 pos = 0;
22547 while(menu_options.find(pos) == menu_options.end())
22548 ++pos;
22549 }
22550 menu_choice* ch = &menu_options[pos];
22551
22552 bool pressed = true;
22553 if(rUp()) pos = ch->upos;
22554 else if(rDown()) pos = ch->dpos;
22555 else if(rLeft()) pos = ch->lpos;
22556 else if(rRight()) pos = ch->rpos;
22557 else pressed = false;
22558
22559 if(pressed)
22560 msg_menu_data[MNU_TIMER] = 1;
22561
22562 bool hold_input = !((msg_menu_data[MNU_TIMER]++) % 5);
22563 bool held = false;
22564 if(hold_input)
22565 {
22566 held = true;
22567 if(Up()) pos = ch->upos;
22568 else if(Down()) pos = ch->dpos;
22569 else if(Left()) pos = ch->lpos;
22570 else if(Right()) pos = ch->rpos;
22571 else held = false;
22572 }
22573 //If the cursor is at an invalid pos, find the first pos >= 0...
22574 if(menu_options.find(pos) == menu_options.end())
22575 {
22576 pos = 0;
22577 while(menu_options.find(pos) == menu_options.end())
22578 ++pos;
22579 }
22580 if((pressed || held) && pos != msg_menu_data[MNU_CHOSEN])
22581 sfx(MsgStrings[msgstr].sfx);
22582
22583 ch = &menu_options[pos];
22584 overtileblock16(msg_menu_bmp_buf, msg_menu_data[MNU_CURSOR_TILE],
22585 ch->x, ch->y, (int32_t)ceil(msg_menu_data[MNU_CURSOR_WID]/16.0),
22586 (int32_t)ceil(msg_menu_data[MNU_CURSOR_HEI]/16.0),
22587 msg_menu_data[MNU_CURSOR_CSET], msg_menu_data[MNU_CURSOR_FLIP]);
22588
22589 msg_menu_data[MNU_CHOSEN] = pos;
22590
22591 if(!msg_menu_data[MNU_CAN_CONFIRM]) //Prevent instantly accepting when holding A
22592 {
22593 rAbtn(); //Eat
22594 if(!cAbtn()) msg_menu_data[MNU_CAN_CONFIRM] = 1;
22595 }
22596
22597 bool ret = (pressed || held) ? false : rAbtn();
22598 //Eat inputs
22599 rUp(); rDown(); rLeft(); rRight(); rAbtn();
22600
22601 if(ret)
22602 menu_options.clear();
22603
22604 return ret;
22605 //false if pos changed this frame; no confirming while moving the cursor!
22606 }
22607
22608 297 bool bottom_margin_clip()
22609 {
22610 297 return !get_bit(quest_rules, qr_OLD_STRING_EDITOR_MARGINS)
22611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
297 && cursor_y >= (msg_h + (get_bit(quest_rules,qr_STRING_FRAME_OLD_WIDTH_HEIGHT)?16:0) - msg_margins[down]);
22612 }
22613
22614 38 bool parsemsgcode()
22615 {
22616
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37 times.
38 if(msgptr>=MsgStrings[msgstr].s.size()) return false;
22617 37 byte c = byte(MsgStrings[msgstr].s[msgptr]-1);
22618
1/36
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
37 switch(c)
22619 {
22620 case MSGC_NEWLINE:
22621 {
22622 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
22623 ssc_tile_hei = ssc_tile_hei_buf;
22624 ssc_tile_hei_buf = -1;
22625 cursor_y += thei + MsgStrings[msgstr].vspace;
22626 cursor_x=msg_margins[left];
22627 return true;
22628 }
22629
22630 case MSGC_COLOUR:
22631 {
22632 int32_t cset = (grab_next_argument());
22633 msgcolour = CSET(cset)+(grab_next_argument());
22634 return true;
22635 }
22636
22637 case MSGC_SHDCOLOR:
22638 {
22639 int32_t cset = (grab_next_argument());
22640 msg_shdcol = CSET(cset)+(grab_next_argument());
22641 return true;
22642 }
22643 case MSGC_SHDTYPE:
22644 {
22645 msg_shdtype = grab_next_argument();
22646 return true;
22647 }
22648
22649 case MSGC_SPEED:
22650 {
22651 msgspeed=grab_next_argument();
22652 return true;
22653 }
22654
22655 case MSGC_CTRUP:
22656 {
22657 int32_t a1 = grab_next_argument();
22658 int32_t a2 = grab_next_argument();
22659 game->change_counter(a2, a1);
22660 return true;
22661 }
22662
22663 case MSGC_CTRDN:
22664 {
22665 int32_t a1 = grab_next_argument();
22666 int32_t a2 = grab_next_argument();
22667 game->change_counter(-a2, a1);
22668 return true;
22669 }
22670
22671 case MSGC_CTRSET:
22672 {
22673 int32_t a1 = grab_next_argument();
22674 int32_t a2 = grab_next_argument();
22675 game->set_counter(vbound(a2, 0, game->get_maxcounter(a1)), a1);
22676 return true;
22677 }
22678
22679 case MSGC_CTRUPPC:
22680 case MSGC_CTRDNPC:
22681 case MSGC_CTRSETPC:
22682 {
22683 int32_t code = MsgStrings[msgstr].s[msgptr]-1;
22684 int32_t counter = grab_next_argument();
22685 int32_t amount = grab_next_argument();
22686 amount = int32_t(vbound(amount*0.01, 0.0, 1.0)*game->get_maxcounter(counter));
22687
22688 if(code==MSGC_CTRDNPC)
22689 amount*=-1;
22690
22691 if(code==MSGC_CTRSETPC)
22692 game->set_counter(amount, counter);
22693 else
22694 game->change_counter(amount, counter);
22695
22696 return true;
22697 }
22698
22699 case MSGC_GIVEITEM:
22700 {
22701 int32_t itemID = grab_next_argument();
22702
22703 getitem(itemID, true);
22704 if ( !item_doscript[itemID] && (((unsigned)itemID) < 256) )
22705 {
22706 itemScriptData[itemID].Clear();
22707 memset(item_stack[itemID], 0xFFFF, MAX_SCRIPT_REGISTERS * sizeof(int32_t));
22708 if ( (itemsbuf[itemID].flags&ITEM_PASSIVESCRIPT) ) item_doscript[itemID] = 1;
22709 }
22710 return true;
22711 }
22712
22713
22714 case MSGC_WARP:
22715 {
22716 int32_t dmap = grab_next_argument();
22717 int32_t scrn = grab_next_argument();
22718 int32_t dx = grab_next_argument();
22719 int32_t dy = grab_next_argument();
22720 int32_t wfx = grab_next_argument();
22721 int32_t sfx = grab_next_argument();
22722 if(dx >= MAX_SCC_ARG) dx = -1;
22723 if(dy >= MAX_SCC_ARG) dy = -1;
22724 FFCore.warp_player(wtIWARP, dmap, scrn, dx, dy, wfx, sfx, warpFlagDONTKILLMUSIC, 0);
22725 return true;
22726 }
22727
22728 case MSGC_SETSCREEND:
22729 {
22730 int32_t dmap = (grab_next_argument()<<7); //dmap and screen may be transposed here.
22731 int32_t screen = grab_next_argument();
22732 int32_t reg = grab_next_argument();
22733 int32_t val = grab_next_argument();
22734 FFCore.set_screen_d(screen + dmap, reg, val);
22735 return true;
22736 }
22737 case MSGC_TAKEITEM:
22738 {
22739 int32_t itemID = grab_next_argument();
22740 if ( item_doscript[itemID] )
22741 {
22742 item_doscript[itemID] = 4; //Val of 4 means 'clear stack and quit'
22743 }
22744 takeitem(itemID);
22745 if ( game->forced_bwpn == itemID )
22746 {
22747 game->forced_bwpn = -1;
22748 } //not else if! -Z
22749 if ( game->forced_awpn == itemID )
22750 {
22751 game->forced_awpn = -1;
22752 }
22753 if ( game->forced_xwpn == itemID )
22754 {
22755 game->forced_xwpn = -1;
22756 } //not else if! -Z
22757 if ( game->forced_ywpn == itemID )
22758 {
22759 game->forced_ywpn = -1;
22760 }
22761 verifyBothWeapons();
22762 return true;
22763 }
22764
22765 case MSGC_SFX:
22766 {
22767 sfx((int32_t)grab_next_argument(),128);
22768 return true;
22769 }
22770
22771 case MSGC_MIDI:
22772 {
22773 int32_t music = (int32_t)(grab_next_argument());
22774
22775 if(music==0)
22776 music_stop();
22777 else
22778 jukebox(music+(ZC_MIDI_COUNT-1));
22779
22780 return true;
22781 }
22782
22783 case MSGC_NAME:
22784 {
22785 doing_name_insert = true;
22786 sprintf(namebuf, "%s", game->get_name());
22787 nameptr = namebuf;
22788 return true;
22789 }
22790
22791 case MSGC_DRAWTILE:
22792 {
22793 int32_t tl = grab_next_argument();
22794 int32_t cs = grab_next_argument();
22795 int32_t t_wid = grab_next_argument();
22796 int32_t t_hei = grab_next_argument();
22797 int32_t fl = grab_next_argument();
22798
22799 if(cursor_x+MsgStrings[msgstr].hspace + t_wid > msg_w-msg_margins[right])
22800 {
22801 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
22802 ssc_tile_hei = ssc_tile_hei_buf;
22803 ssc_tile_hei_buf = -1;
22804 cursor_y += thei + MsgStrings[msgstr].vspace;
22805 if(bottom_margin_clip()) return true;
22806 cursor_x=msg_margins[left];
22807 }
22808
22809 overtileblock16(msg_txt_bmp_buf, tl, cursor_x, cursor_y, (int32_t)ceil(t_wid/16.0), (int32_t)ceil(t_hei/16.0), cs, fl);
22810 ssc_tile_hei_buf = zc_max(ssc_tile_hei_buf, t_hei);
22811 cursor_x += MsgStrings[msgstr].hspace + t_wid;
22812 return true;
22813 }
22814
22815 case MSGC_GOTOIFRAND:
22816 {
22817 int32_t odds = (int32_t)(grab_next_argument());
22818
22819 if(!odds || !(zc_oldrand()%odds))
22820 goto switched;
22821
22822 (void)grab_next_argument();
22823 return true;
22824 }
22825
22826 case MSGC_GOTOIFGLOBAL:
22827 {
22828 int32_t arg = (int32_t)grab_next_argument();
22829 int32_t d = zc_min(7,arg);
22830 int32_t s = ((get_currdmap())<<7) + get_currscr()-(DMaps[get_currdmap()].type==dmOVERW ? 0 : DMaps[get_currdmap()].xoff);
22831 arg = (int32_t)grab_next_argument();
22832
22833 if(game->screen_d[s][d] >= arg)
22834 goto switched;
22835
22836 (void)grab_next_argument();
22837 return true;
22838 }
22839
22840 case MSGC_CHANGEPORTRAIT:
22841 {
22842 return true; //not implemented
22843 }
22844
22845 case MSGC_GOTOIFCREEND:
22846 {
22847 int32_t dmap = (grab_next_argument()<<7); //dmap and screen may be transposed here.
22848 int32_t screen = grab_next_argument();
22849 int32_t reg = grab_next_argument();
22850 int32_t val = grab_next_argument();
22851 //int32_t nxtstr = grab_next_argument();
22852 if ( FFCore.get_screen_d(screen + dmap, reg) >= val )
22853 {
22854 goto switched;
22855 }
22856 (void)grab_next_argument();
22857 return true;
22858 }
22859
22860 case MSGC_GOTOIF:
22861 {
22862 int32_t it = (int32_t)grab_next_argument();
22863
22864 if(unsigned(it)<MAXITEMS && game->item[it])
22865 goto switched;
22866
22867 (void)grab_next_argument();
22868 return true;
22869 }
22870
22871 case MSGC_GOTOIFCTR:
22872 {
22873 if(game->get_counter(grab_next_argument())>=grab_next_argument())
22874 goto switched;
22875
22876 (void)grab_next_argument();
22877 return true;
22878 }
22879
22880 case MSGC_GOTOIFCTRPC:
22881 {
22882 int32_t counter = grab_next_argument();
22883 int32_t amount = (int32_t)(((grab_next_argument())/100)*game->get_maxcounter(counter));
22884
22885 if(game->get_counter(counter)>=amount)
22886 goto switched;
22887
22888 (void)grab_next_argument();
22889 return true;
22890 }
22891
22892 case MSGC_GOTOIFTRICOUNT:
22893 {
22894 if(TriforceCount() >= (int32_t)(grab_next_argument()))
22895 goto switched;
22896
22897 (void)grab_next_argument();
22898 return true;
22899 }
22900
22901 case MSGC_GOTOIFTRI:
22902 {
22903 int32_t lev = (int32_t)(grab_next_argument());
22904
22905 if(lev<MAXLEVELS && game->lvlitems[lev]&liTRIFORCE)
22906 goto switched;
22907
22908 (void)grab_next_argument();
22909 return true;
22910 }
22911
22912 case MSGC_SETUPMENU:
22913 {
22914 msg_menu_data[MNU_CURSOR_TILE] = grab_next_argument();
22915 msg_menu_data[MNU_CURSOR_CSET] = grab_next_argument();
22916 msg_menu_data[MNU_CURSOR_WID] = grab_next_argument();
22917 msg_menu_data[MNU_CURSOR_HEI] = grab_next_argument();
22918 msg_menu_data[MNU_CURSOR_FLIP] = grab_next_argument();
22919 return true;
22920 }
22921
22922 case MSGC_MENUCHOICE:
22923 {
22924 int32_t pos = grab_next_argument();
22925 int32_t upos = grab_next_argument();
22926 int32_t dpos = grab_next_argument();
22927 int32_t lpos = grab_next_argument();
22928 int32_t rpos = grab_next_argument();
22929 if(cursor_x+MsgStrings[msgstr].hspace + msg_menu_data[MNU_CURSOR_WID] > msg_w-msg_margins[right])
22930 {
22931 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
22932 ssc_tile_hei = ssc_tile_hei_buf;
22933 ssc_tile_hei_buf = -1;
22934 cursor_y += thei + MsgStrings[msgstr].vspace;
22935 if(bottom_margin_clip()) break;
22936 cursor_x=msg_margins[left];
22937 }
22938
22939 menu_options[pos] = menu_choice(cursor_x, cursor_y, pos,
22940 upos, dpos, lpos, rpos);
22941
22942 ssc_tile_hei_buf = zc_max(ssc_tile_hei_buf, msg_menu_data[MNU_CURSOR_HEI]);
22943 cursor_x += MsgStrings[msgstr].hspace + msg_menu_data[MNU_CURSOR_WID];
22944 return true;
22945 }
22946
22947 case MSGC_RUNMENU:
22948 {
22949 msg_menu_data[MNU_CHOSEN] = 0;
22950 msg_menu_data[MNU_CAN_CONFIRM] = 0;
22951 if(menu_options.size() < 1)
22952 return true;
22953 do_run_menu = true;
22954 return true;
22955 }
22956
22957 case MSGC_GOTOMENUCHOICE:
22958 {
22959 int32_t choice = grab_next_argument();
22960 if(msg_menu_data[MNU_CHOSEN] == choice)
22961 goto switched;
22962 (void)grab_next_argument();
22963 return true;
22964 }
22965
22966 case MSGC_ENDSTRING:
22967 {
22968 do_end_str = true;
22969 return true;
22970 }
22971 case MSGC_WAIT_ADVANCE:
22972 {
22973 wait_advance = true;
22974 linkedmsgclk = 51;
22975 return true;
22976 }
22977 case MSGC_TRIGSECRETS:
22978 {
22979 bool perm = (bool)grab_next_argument();
22980 hidden_entrance(0, true, false, -8);
22981 if(perm)
22982 setmapflag(mSECRET);
22983 return true;
22984 }
22985 case MSGC_SETSCREENSTATE:
22986 {
22987 int32_t flag = int32_t(grab_next_argument());
22988 if(unsigned(flag)>=mMAXIND)
22989 {
22990 Z_error("SCC 133: Flag %d is invalid\n", flag);
22991 return true;
22992 }
22993 bool state = bool(grab_next_argument());
22994 if(state)
22995 setmapflag(1<<flag);
22996 else
22997 unsetmapflag(1<<flag,true);
22998 return true;
22999 }
23000 case MSGC_SETSCREENSTATER:
23001 {
23002 int32_t map = (int32_t)grab_next_argument();
23003 int32_t scrid = (int32_t)grab_next_argument();
23004 if(map < 1 || map > map_count)
23005 {
23006 Z_error("SCC 134: Map %d is invalid\n", map);
23007 return true;
23008 }
23009 if(unsigned(scrid)>=0x80)
23010 {
23011 Z_error("SCC 134: Screen %d is invalid\n", scrid);
23012 return true;
23013 }
23014
23015 int32_t flag = int32_t(grab_next_argument());
23016 if(unsigned(flag)>=mMAXIND)
23017 {
23018 Z_error("SCC 134: Flag %d is invalid\n", flag);
23019 return true;
23020 }
23021 bool state = bool(grab_next_argument());
23022 if(state)
23023 setmapflag(mapind(map,scrid),1<<flag);
23024 else
23025 unsetmapflag(mapind(map,scrid),1<<flag,true);
23026 return true;
23027 }
23028 switched:
23029 int32_t lev = (int32_t)(grab_next_argument());
23030 if(lev && get_bit(quest_rules, qr_SCC_GOTO_RESPECTS_CONTFLAG)
23031 && (MsgStrings[lev].stringflags & STRINGFLAG_CONT))
23032 {
23033 msgstr=lev;
23034 msgpos=msgptr=0;
23035 msgfont=setmsgfont();
23036 }
23037 else donewmsg(lev);
23038 msgptr--; // To counteract it being incremented after this routine is called.
23039 putprices(false);
23040 return true;
23041 }
23042
23043 37 return false;
23044 38 }
23045
23046 // Wraps the message string... probably.
23047 37 void wrapmsgstr(char *s3)
23048 {
23049 37 int32_t j=0;
23050
23051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)
23052 {
23053 if(msgspace)
23054 {
23055 char c = MsgStrings[msgstr].s[msgptr];
23056 if(c != ' ' && c >= 32 && c <= 126)
23057 {
23058 for(int32_t k=0; MsgStrings[msgstr].s[msgptr+k] && MsgStrings[msgstr].s[msgptr+k] != ' '; k++)
23059 {
23060 if(MsgStrings[msgstr].s[msgptr+k] >= 32 && MsgStrings[msgstr].s[msgptr+k] <= 126) s3[j++] = MsgStrings[msgstr].s[msgptr+k];
23061 }
23062
23063 s3[j] = 0;
23064 msgspace = false;
23065 }
23066 else
23067 {
23068 s3[0] = c;
23069 s3[1] = 0;
23070 }
23071 }
23072 else
23073 {
23074 s3[0] = MsgStrings[msgstr].s[msgptr];
23075 s3[1] = 0;
23076
23077 if(s3[0] == ' ') msgspace=true;
23078 }
23079 }
23080 else
23081 {
23082 37 s3[0] = MsgStrings[msgstr].s[msgptr];
23083 37 s3[1] = 0;
23084 }
23085 37 }
23086
23087 // Returns true if the pointer is at a string's
23088 // null terminator or a trailing space
23089 145 bool atend(char const* str)
23090 {
23091 145 int32_t i=0;
23092
23093
2/2
✓ Branch 0 taken 415 times.
✓ Branch 1 taken 145 times.
560 while(str[i]==' ')
23094 415 i++;
23095
23096 145 return str[i]=='\0';
23097 }
23098
23099 1888 void putmsg()
23100 {
23101 1888 bool oldmargin = get_bit(quest_rules, qr_OLD_STRING_EDITOR_MARGINS)!=0;
23102
2/2
✓ Branch 0 taken 1612 times.
✓ Branch 1 taken 276 times.
1888 if(!msgorig) msgorig=msgstr;
23103
23104
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(wait_advance && linkedmsgclk < 1)
23105 linkedmsgclk = 1;
23106
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 if(linkedmsgclk>0)
23107 {
23108 if(linkedmsgclk==1)
23109 {
23110 if(do_end_str||cAbtn()||cBbtn())
23111 {
23112 do_end_str = false;
23113 linkedmsgclk = 0;
23114 if(wait_advance)
23115 {
23116 wait_advance = false;
23117 }
23118 else
23119 {
23120 msgstr=MsgStrings[msgstr].nextstring;
23121 if(!msgstr && enqueued_str)
23122 {
23123 msgstr = enqueued_str;
23124 enqueued_str = 0;
23125 }
23126 if(!msgstr)
23127 {
23128 msgfont=zfont;
23129
23130 if(tmpscr->room!=rGRUMBLE)
23131 blockpath=false;
23132
23133 dismissmsg();
23134 goto disappear;
23135 }
23136
23137 donewmsg(msgstr);
23138 putprices(false);
23139 }
23140 }
23141 }
23142 else
23143 {
23144 --linkedmsgclk;
23145 }
23146 }
23147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if(wait_advance) return; //Waiting for buttonpress
23148
23149
7/10
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 275 times.
✓ Branch 3 taken 1613 times.
✓ Branch 4 taken 275 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 222 times.
✓ Branch 7 taken 53 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 222 times.
1888 if(!do_run_menu && (!msgstr || msgpos>=10000 || msgptr>=MsgStrings[msgstr].s.size() || bottom_margin_clip()))
23150 {
23151
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 1613 times.
1666 if(!msgstr)
23152 1613 msgorig=0;
23153
23154 1666 msg_active = false;
23155 1666 return;
23156 }
23157
23158 222 msg_onscreen = true; // Now the message is onscreen (see donewmsg()).
23159
23160 char s3[145];
23161 int32_t tlength;
23162
23163 // Bypass the string with the B button!
23164
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 222 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 222 times.
222 if(((cBbtn())&&(get_bit(quest_rules,qr_ALLOWMSGBYPASS))) || msgspeed==0)
23165 {
23166 //finish writing out the string
23167 while(msgptr<MsgStrings[msgstr].s.size() && !atend(MsgStrings[msgstr].s.c_str()+msgptr))
23168 {
23169 if(msgspeed && !(cBbtn() && get_bit(quest_rules,qr_ALLOWMSGBYPASS)))
23170 goto breakout; // break out if message speed was changed to non-zero
23171 else if(!do_run_menu && !doing_name_insert && !parsemsgcode())
23172 {
23173 if(bottom_margin_clip())
23174 break;
23175
23176 wrapmsgstr(s3);
23177
23178 if(MsgStrings[msgstr].s[msgptr]==' ')
23179 {
23180 tlength = msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]) + MsgStrings[msgstr].hspace;
23181
23182 if(cursor_x+tlength > (msg_w-msg_margins[right])
23183 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23184 ? true : strcmp(s3," ")!=0))
23185 {
23186 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23187 ssc_tile_hei = ssc_tile_hei_buf;
23188 ssc_tile_hei_buf = -1;
23189 cursor_y += thei + MsgStrings[msgstr].vspace;
23190 if(bottom_margin_clip()) break;
23191 cursor_x=msg_margins[left];
23192 }
23193
23194 char buf[2] = {0};
23195 sprintf(buf,"%c",MsgStrings[msgstr].s[msgptr]);
23196
23197 textout_styled_aligned_ex(msg_txt_bmp_buf,msgfont,buf,cursor_x,cursor_y,msg_shdtype,sstaLEFT,msgcolour,msg_shdcol,-1);
23198
23199 cursor_x+=tlength;
23200 }
23201 else
23202 {
23203 tlength = text_length(msgfont, s3) + ((int32_t)strlen(s3)*MsgStrings[msgstr].hspace);
23204 if(cursor_x+tlength > (msg_w-msg_margins[right])
23205 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23206 ? true : strcmp(s3," ")!=0))
23207 {
23208 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23209 ssc_tile_hei = ssc_tile_hei_buf;
23210 ssc_tile_hei_buf = -1;
23211 cursor_y += thei + MsgStrings[msgstr].vspace;
23212 if(bottom_margin_clip()) break;
23213 cursor_x=msg_margins[left];
23214 }
23215
23216 sfx(MsgStrings[msgstr].sfx);
23217
23218 char buf[2] = {0};
23219 sprintf(buf,"%c",MsgStrings[msgstr].s[msgptr]);
23220
23221 textout_styled_aligned_ex(msg_txt_bmp_buf,msgfont,buf,cursor_x,cursor_y,msg_shdtype,sstaLEFT,msgcolour,msg_shdcol,-1);
23222
23223 cursor_x += msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]);
23224 cursor_x += MsgStrings[msgstr].hspace;
23225 }
23226
23227 msgpos++;
23228 }
23229 if(do_run_menu)
23230 {
23231 if(runMenuCursor())
23232 {
23233 do_run_menu = false;
23234 }
23235 else break;
23236 }
23237 if(doing_name_insert)
23238 {
23239 if(*nameptr)
23240 {
23241 if(bottom_margin_clip())
23242 break;
23243
23244 char s3[9] = {0};
23245
23246 if(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)
23247 {
23248 strcpy(s3, nameptr);
23249 }
23250 else
23251 {
23252 s3[0] = *nameptr;
23253 s3[1] = 0;
23254 }
23255
23256 tlength = text_length(msgfont, s3) + ((int32_t)strlen(s3)*MsgStrings[msgstr].hspace);
23257
23258 if(cursor_x+tlength > (msg_w-msg_margins[right])
23259 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23260 ? true : strcmp(s3," ")!=0))
23261 {
23262 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23263 ssc_tile_hei = ssc_tile_hei_buf;
23264 ssc_tile_hei_buf = -1;
23265 cursor_y += thei + MsgStrings[msgstr].vspace;
23266 if(bottom_margin_clip()) break;
23267 cursor_x=msg_margins[left];
23268 }
23269
23270 sfx(MsgStrings[msgstr].sfx);
23271
23272 char buf[2] = {0};
23273 sprintf(buf,"%c",*nameptr);
23274
23275 textout_styled_aligned_ex(msg_txt_bmp_buf,msgfont,buf,cursor_x,cursor_y,msg_shdtype,sstaLEFT,msgcolour,msg_shdcol,-1);
23276
23277 cursor_x += msgfont->vtable->char_length(msgfont, *nameptr);
23278 cursor_x += MsgStrings[msgstr].hspace;
23279 ++nameptr;
23280 continue; //don't advance the msgptr, as the next char in it was not processed!
23281 }
23282 else doing_name_insert = false;
23283 }
23284 ++msgptr;
23285 if(do_end_str)
23286 goto strendcheck;
23287 if(wait_advance)
23288 return;
23289 if(atend(MsgStrings[msgstr].s.c_str()+msgptr))
23290 {
23291 if(MsgStrings[msgstr].nextstring)
23292 {
23293 if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
23294 {
23295 msgstr=MsgStrings[msgstr].nextstring;
23296 msgpos=msgptr=0;
23297 msgfont=setmsgfont();
23298 }
23299 }
23300 }
23301 }
23302
23303 if (!do_run_menu)
23304 {
23305 msgclk = 72;
23306 msgpos = 10000;
23307 }
23308 }
23309 else
23310 222 {
23311 breakout:
23312
23313
3/6
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 185 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
222 if(((msgclk++)%(msgspeed+1)<msgspeed)&&((!cAbtn())||(!get_bit(quest_rules,qr_ALLOWFASTMSG))))
23314 185 return;
23315 }
23316
23317 // Start writing the string
23318
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1 times.
38 if(msgptr == 0)
23319 {
23320
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 while(MsgStrings[msgstr].s[msgptr]==' ')
23321 {
23322 2 tlength = msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]) + MsgStrings[msgstr].hspace;
23323
23324
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
2 if(cursor_x+tlength > (msg_w-msg_margins[right])
23325
1/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23326 ? 1 : strcmp(s3," ")!=0))
23327 {
23328 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23329 ssc_tile_hei = ssc_tile_hei_buf;
23330 ssc_tile_hei_buf = -1;
23331 cursor_y += thei + MsgStrings[msgstr].vspace;
23332 if(bottom_margin_clip()) break;
23333 cursor_x=msg_margins[left];
23334 }
23335
23336 2 cursor_x+=tlength;
23337 2 ++msgptr;
23338 2 ++msgpos;
23339
23340 // The "Continue From Previous" feature
23341
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(atend(MsgStrings[msgstr].s.c_str()+msgptr))
23342 {
23343 if(MsgStrings[msgstr].nextstring)
23344 {
23345 if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
23346 {
23347 msgstr=MsgStrings[msgstr].nextstring;
23348 msgpos=msgptr=0;
23349 msgfont=setmsgfont();
23350 }
23351 }
23352 }
23353 }
23354 1 }
23355
23356 reparsesinglechar:
23357 // Continue printing the string!
23358
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
74 if(!atend(MsgStrings[msgstr].s.c_str()+msgptr) && !bottom_margin_clip())
23359 {
23360
3/6
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
37 if(!do_run_menu && !doing_name_insert && !parsemsgcode())
23361 {
23362 37 wrapmsgstr(s3);
23363
23364 37 tlength = text_length(msgfont, s3) + ((int32_t)strlen(s3)*MsgStrings[msgstr].hspace);
23365
23366
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
37 if(cursor_x+tlength > (msg_w-msg_margins[right])
23367
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
37 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23368 ? true : strcmp(s3," ")!=0))
23369 {
23370 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23371 ssc_tile_hei = ssc_tile_hei_buf;
23372 ssc_tile_hei_buf = -1;
23373 cursor_y += thei + MsgStrings[msgstr].vspace;
23374 if(bottom_margin_clip()) goto strendcheck;
23375 cursor_x=msg_margins[left];
23376 //if(space) s3[0]=0;
23377 }
23378
23379 37 sfx(MsgStrings[msgstr].sfx);
23380
23381 37 char buf[2] = {0};
23382 37 sprintf(buf,"%c",MsgStrings[msgstr].s[msgptr]);
23383
23384 37 textout_styled_aligned_ex(msg_txt_bmp_buf,msgfont,buf,cursor_x,cursor_y,msg_shdtype,sstaLEFT,msgcolour,msg_shdcol,-1);
23385
23386 37 cursor_x += msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]);
23387 37 cursor_x += MsgStrings[msgstr].hspace;
23388 37 msgpos++;
23389 37 }
23390
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if(do_end_str)
23391 goto strendcheck;
23392
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if(wait_advance)
23393 {
23394 ++msgptr;
23395 return;
23396 }
23397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 else if(do_run_menu)
23398 {
23399 if(runMenuCursor())
23400 {
23401 do_run_menu = false;
23402 ++msgptr;
23403 goto reparsesinglechar;
23404 }
23405 }
23406
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
37 else if(doing_name_insert && *nameptr)
23407 {
23408 char s3[9] = {0};
23409
23410 if(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)
23411 {
23412 strcpy(s3, nameptr);
23413 }
23414 else
23415 {
23416 s3[0] = *nameptr;
23417 s3[1] = 0;
23418 }
23419
23420 tlength = text_length(msgfont, s3) + ((int32_t)strlen(s3)*MsgStrings[msgstr].hspace);
23421
23422 if(cursor_x+tlength > (msg_w-msg_margins[right])
23423 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23424 ? true : strcmp(s3," ")!=0))
23425 {
23426 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23427 ssc_tile_hei = ssc_tile_hei_buf;
23428 ssc_tile_hei_buf = -1;
23429 cursor_y += thei + MsgStrings[msgstr].vspace;
23430 if(bottom_margin_clip()) goto strendcheck;
23431 cursor_x=msg_margins[left];
23432 }
23433
23434 sfx(MsgStrings[msgstr].sfx);
23435
23436 char buf[2] = {0};
23437 sprintf(buf,"%c",*nameptr);
23438
23439 textout_styled_aligned_ex(msg_txt_bmp_buf,msgfont,buf,cursor_x,cursor_y,msg_shdtype,sstaLEFT,msgcolour,msg_shdcol,-1);
23440
23441 cursor_x += msgfont->vtable->char_length(msgfont, *nameptr);
23442 cursor_x += MsgStrings[msgstr].hspace;
23443 ++nameptr;
23444 }
23445 else
23446 {
23447 37 doing_name_insert = false;
23448 37 msgptr++;
23449
23450
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1 times.
37 if(atend(MsgStrings[msgstr].s.c_str()+msgptr))
23451 {
23452
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(MsgStrings[msgstr].nextstring)
23453 {
23454 if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
23455 {
23456 msgstr=MsgStrings[msgstr].nextstring;
23457 msgpos=msgptr=0;
23458 msgfont=setmsgfont();
23459 }
23460 }
23461 1 }
23462
23463
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
44 if(MsgStrings[msgstr].s.size() > unsigned(msgptr+1)
23464
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 && (MsgStrings[msgstr].s[msgptr]==' ')
23465
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 30 times.
37 && (MsgStrings[msgstr].s[msgptr+1]==' '))
23466 {
23467
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 33 times.
35 while(MsgStrings[msgstr].s[msgptr]==' ')
23468 {
23469 33 msgspace = true;
23470 33 tlength = msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]) + MsgStrings[msgstr].hspace;
23471
23472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
35 if(cursor_x+tlength > (msg_w-msg_margins[right])
23473
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
33 && ((cursor_x > (msg_w-msg_margins[right]) || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP))
23474 ? true : strcmp(s3," ")!=0))
23475 {
23476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 int32_t thei = zc_max(ssc_tile_hei, text_height(msgfont));
23477 2 ssc_tile_hei = ssc_tile_hei_buf;
23478 2 ssc_tile_hei_buf = -1;
23479 2 cursor_y += thei + MsgStrings[msgstr].vspace;
23480
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(bottom_margin_clip()) break;
23481 2 cursor_x=msg_margins[left];
23482 2 }
23483
23484 33 cursor_x+=tlength;
23485 33 ++msgpos;
23486 33 ++msgptr;
23487
23488
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 27 times.
33 if(atend(MsgStrings[msgstr].s.c_str()+msgptr))
23489 {
23490
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if(MsgStrings[msgstr].nextstring)
23491 {
23492 if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
23493 {
23494 msgstr=MsgStrings[msgstr].nextstring;
23495 msgpos=msgptr=0;
23496 msgfont=setmsgfont();
23497 }
23498 }
23499 27 }
23500 }
23501 2 }
23502 }
23503 37 }
23504 strendcheck:
23505 // Done printing the string
23506
9/14
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 36 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 36 times.
✓ Branch 13 taken 1 times.
37 if(do_end_str || !doing_name_insert && !do_run_menu && (msgpos>=10000 || msgptr>=MsgStrings[msgstr].s.size() || bottom_margin_clip() || atend(MsgStrings[msgstr].s.c_str()+msgptr)) && !linkedmsgclk)
23507 {
23508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(!do_end_str)
23509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 while(parsemsgcode()); // Finish remaining control codes
23510
23511 // Go to next string, or make it disappear by going to string 0.
23512
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if(MsgStrings[msgstr].nextstring!=0 || get_bit(quest_rules,qr_MSGDISAPPEAR) || enqueued_str)
23513 {
23514 linkedmsgclk=do_end_str?1:51;
23515 }
23516
23517
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(MsgStrings[msgstr].nextstring==0)
23518 {
23519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(!get_bit(quest_rules,qr_MSGDISAPPEAR))
23520 1 {
23521 disappear:
23522 1 msg_active = false;
23523 1 Hero.finishedmsg();
23524 1 }
23525
23526
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(repaircharge)
23527 {
23528 // if (get_bit(quest_rules,qr_REPAIRFIX)) {
23529 // fixed_door=true;
23530 // }
23531 game->change_drupy(-tmpscr[currscr<128?0:1].catchall);
23532 repaircharge = 0;
23533 }
23534
23535
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(adjustmagic)
23536 {
23537 if(get_bit(quest_rules,qr_OLD_HALF_MAGIC))
23538 {
23539 if(game->get_magicdrainrate())
23540 game->set_magicdrainrate(1);
23541 }
23542 else if(game->get_magicdrainrate() > 1)
23543 {
23544 game->set_magicdrainrate(game->get_magicdrainrate()/2);
23545 }
23546 adjustmagic = false;
23547 sfx(WAV_SCALE);
23548 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
23549 }
23550
23551
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(learnslash)
23552 {
23553 game->set_canslash(1);
23554 learnslash = false;
23555 sfx(WAV_SCALE);
23556 setmapflag((currscr < 128 && get_bit(quest_rules, qr_ITEMPICKUPSETSBELOW)) ? mITEM : mSPECIALITEM);
23557 }
23558 1 }
23559 1 }
23560 1888 }
23561
23562 int32_t message_more_y()
23563 {
23564 //Is the flag ticked, do we really want a message more y larger than 160?
23565 int32_t msgy=zc_min((zinit.msg_more_is_offset==0)?zinit.msg_more_y:zinit.msg_more_y+MsgStrings[msgstr].y ,160);
23566 msgy+=playing_field_offset;
23567 return msgy;
23568 }
23569
23570 /*** Collision detection & handling ***/
23571
23572 1888 void clear_script_one_frame_conditions()
23573 {
23574
2/2
✓ Branch 0 taken 3769 times.
✓ Branch 1 taken 1888 times.
5657 for(int32_t j=0; j<guys.Count(); j++)
23575 {
23576 3769 enemy *e = (enemy*)guys.spr(j);
23577
2/2
✓ Branch 0 taken 60304 times.
✓ Branch 1 taken 3769 times.
64073 for ( int32_t q = 0; q < NUM_HIT_TYPES_USED; q++ ) e->hitby[q] = 0;
23578 3769 }
23579 1888 }
23580
23581 1888 void check_collisions()
23582 {
23583 1888 bool temp_hit = false;
23584
2/2
✓ Branch 0 taken 739 times.
✓ Branch 1 taken 1888 times.
2627 for(int32_t i=0; i<Lwpns.Count(); i++)
23585 {
23586 739 weapon *w = (weapon*)Lwpns.spr(i);
23587
23588
6/8
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 322 times.
✓ Branch 3 taken 153 times.
✓ Branch 4 taken 322 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 322 times.
739 if(!(w->Dead()) && w->id!=wSword && w->id!=wHammer && w->id!=wWand)
23589 {
23590
2/2
✓ Branch 0 taken 316 times.
✓ Branch 1 taken 722 times.
1038 for(int32_t j=0; j<guys.Count(); j++)
23591 {
23592 722 enemy *e = (enemy*)guys.spr(j);
23593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 722 times.
722 if ( !temp_hit ) e->hitby[HIT_BY_LWEAPON] = 0;
23594
23595
2/2
✓ Branch 0 taken 716 times.
✓ Branch 1 taken 6 times.
722 if(e->hit(w)) //boomerangs and such that last for more than a frame can write hitby[] for more than one frame,
23596 //because this only checks `if(dying || clk<0 || hclk>0 || superman)`
23597 {
23598 // !(e->stunclk)
23599 6 int32_t h = e->takehit(w);
23600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (h == -1)
23601 {
23602 6 e->hitby[HIT_BY_LWEAPON] = i+1; temp_hit = true;
23603 6 e->hitby[HIT_BY_LWEAPON_UID] = w->script_UID;
23604 //e->hitby[HIT_BY_LWEAPON_FAMILY] = itemsbuf[w->parentid].family; //that would be the itemclass, not the weapon type!
23605 6 e->hitby[HIT_BY_LWEAPON_FAMILY] = w->id;
23606 //al_trace("npc->HitBy[] Parent Item is: %d /n", w->parentitem);
23607 //al_trace("npc->HitBy[] Parent ID is: %d /n", w->parentid);
23608 6 e->hitby[HIT_BY_LWEAPON_LITERAL_ID] = w->parentitem;
23609
23610 6 }
23611 //we may need to handle this in special cases. -Z
23612
23613 //if h == stun or ignore
23614
23615 //if e->stun > DEFAULT_STUN -1 || !e->stun
23616 //if the enemy wasn't stunned this round -- what a bitch, as the stun value is set before we check this
23617 ///! how about: if w->dead != bounce !
23618
23619 // NOT FOR PUBLIC RELEASE
23620 /*if(h==3) //Mirror shield
23621 {
23622 if (w->id==ewFireball || w->id==wRefFireball)
23623 {
23624 w->id=wRefFireball;
23625 switch(e->dir)
23626 {
23627 case up: e->angle += (PI - e->angle) * 2.0; break;
23628 case down: e->angle = -e->angle; break;
23629 case left: e->angle += ((-PI/2) - e->angle) * 2.0; break;
23630 case right: e->angle += (( PI/2) - e->angle) * 2.0; break;
23631 // TODO: the following. -L.
23632 case l_up: break;
23633 case r_up: break;
23634 case l_down: break;
23635 case r_down: break;
23636 }
23637 }
23638 else
23639 {
23640 w->id = ((w->id==ewMagic || w->id==wRefMagic || w->id==wMagic) ? wRefMagic : wRefBeam);
23641 w->dir ^= 1;
23642 if(w->dir&2)
23643 w->flip ^= 1;
23644 else
23645 w->flip ^= 2;
23646 }
23647 w->ignoreHero=false;
23648 }
23649 else*/
23650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(h)
23651 {
23652
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if(e->switch_hooked && w->family_class == itype_switchhook)
23653 w->onhit(false, e, -1);
23654 6 else w->onhit(false, e, h);
23655 6 }
23656
23657
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(h==2)
23658 {
23659 break;
23660 }
23661 6 }
23662
23663
2/2
✓ Branch 0 taken 716 times.
✓ Branch 1 taken 6 times.
722 if(w->Dead())
23664 {
23665 6 break;
23666 }
23667 716 }
23668
23669 // Item flags added in 2.55:
23670 // BRang/HShot/Arrows ITEM_FLAG4 is "Pick up anything" (port of qr_BRANGPICKUP)
23671 // BRang/HShot ITEM_FLAG5 is "Drags Items" (port of qr_Z3BRANG_HSHOT)
23672 // Arrows ITEM_FLAG2 is "Picks up items" (inverse port of qr_Z3BRANG_HSHOT)
23673 // -V
23674
3/6
✓ Branch 0 taken 322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 322 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 322 times.
322 if(w->id == wBrang || w->id == wHookshot || w->id == wArrow)
23675 {
23676 int32_t itype, pitem = w->parentitem;
23677 switch(w->id)
23678 {
23679 case wBrang: itype = itype_brang; break;
23680 case wArrow: itype = itype_arrow; break;
23681 case wHookshot:
23682 itype = (w->family_class == itype_switchhook ? itype_switchhook :itype_hookshot);
23683 break;
23684 }
23685 if(pitem < 0) pitem = current_item_id(itype);
23686 if(w->id == wHookshot && w->family_class == itype_switchhook && (itemsbuf[pitem].flags & ITEM_FLAG9))
23687 { //Swap with item
23688 for(int32_t j=0; j<items.Count(); j++)
23689 {
23690 if(items.spr(j)->hit(w))
23691 {
23692 item *theItem = ((item*)items.spr(j));
23693 bool priced = theItem->PriceIndex >-1;
23694 bool isKey = itemsbuf[theItem->id].family==itype_key||itemsbuf[theItem->id].family==itype_lkey;
23695 if(!theItem->fallclk && !theItem->drownclk && ((theItem->pickup & ipTIMER && theItem->clk2 >= 32)
23696 || (((itemsbuf[w->parentitem].flags & ITEM_FLAG4)||(theItem->pickup & ipCANGRAB)||((itemsbuf[w->parentitem].flags & ITEM_FLAG7)&&isKey)) && !priced && !(theItem->pickup & ipDUMMY))))
23697 {
23698 if(!Hero.switchhookclk)
23699 {
23700 hooked_combopos = -1;
23701 hooked_layerbits = 0;
23702 switching_object = theItem;
23703 theItem->switch_hooked = true;
23704 w->misc = 2;
23705 w->step = 0;
23706 theItem->clk2=256;
23707 Hero.doSwitchHook(game->get_switchhookstyle());
23708 if(QMisc.miscsfx[sfxSWITCHED])
23709 sfx(QMisc.miscsfx[sfxSWITCHED],int32_t(w->x));
23710 }
23711 }
23712 }
23713 }
23714 }
23715 else if((w->id==wArrow&&itemsbuf[pitem].flags & ITEM_FLAG2)||(w->id!=wArrow&&!(itemsbuf[pitem].flags & ITEM_FLAG5)))//An arrow with "Picks up items" or a BRang/HShot without "Drags items"
23716 {
23717 for(int32_t j=0; j<items.Count(); j++)
23718 {
23719 if(items.spr(j)->hit(w))
23720 {
23721 item *theItem = ((item*)items.spr(j));
23722 bool priced = theItem->PriceIndex >-1;
23723 bool isKey = itemsbuf[theItem->id].family==itype_key||itemsbuf[theItem->id].family==itype_lkey;
23724 if(!theItem->fallclk && !theItem->drownclk && ((theItem->pickup & ipTIMER && theItem->clk2 >= 32)
23725 || (((itemsbuf[pitem].flags & ITEM_FLAG4)||(theItem->pickup & ipCANGRAB)||((itemsbuf[pitem].flags & ITEM_FLAG7)&&isKey))&& !priced)))
23726 {
23727 if(itemsbuf[theItem->id].collect_script)
23728 {
23729 ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[theItem->id].collect_script, theItem->id & 0xFFF);
23730 }
23731
23732 Hero.checkitems(j);
23733 }
23734 }
23735 }
23736 }
23737 else if(w->id!=wArrow) //A BRang/HShot with "Drags Items"
23738 {
23739 for(int32_t j=0; j<items.Count(); j++)
23740 {
23741 if(items.spr(j)->hit(w))
23742 {
23743 item *theItem = ((item*)items.spr(j));
23744 bool priced = theItem->PriceIndex >-1;
23745 bool isKey = itemsbuf[theItem->id].family==itype_key||itemsbuf[theItem->id].family==itype_lkey;
23746 if(!theItem->fallclk && !theItem->drownclk && ((theItem->pickup & ipTIMER && theItem->clk2 >= 32)
23747 || (((itemsbuf[pitem].flags & ITEM_FLAG4)||(theItem->pickup & ipCANGRAB)||((itemsbuf[pitem].flags & ITEM_FLAG7)&&isKey)) && !priced && !(theItem->pickup & ipDUMMY))))
23748 {
23749 int32_t pickup = theItem->pickup;
23750 int32_t id2 = theItem->id;
23751 int32_t pstr = theItem->pstring;
23752 int32_t pstr_flags = theItem->pickup_string_flags;
23753
23754 std::vector<int32_t> &ev = FFCore.eventData;
23755 ev.clear();
23756 ev.push_back(id2*10000);
23757 ev.push_back(pickup*10000);
23758 ev.push_back(pstr*10000);
23759 ev.push_back(pstr_flags*10000);
23760 ev.push_back(0);
23761 ev.push_back(theItem->getUID());
23762 ev.push_back(GENEVT_ICTYPE_RANGED_DRAG*10000);
23763 ev.push_back(w->getUID());
23764
23765 throwGenScriptEvent(GENSCR_EVENT_COLLECT_ITEM);
23766 bool nullify = ev[4] != 0;
23767 if(nullify) continue;
23768 if(w->id == wBrang)
23769 {
23770 w->onhit(false);
23771 }
23772
23773 if(w->dragging==-1)
23774 {
23775 w->dead=1;
23776 theItem->clk2=256;
23777 w->dragging=j;
23778 theItem->is_dragged = true;
23779 }
23780 }
23781 }
23782 }
23783 }
23784 }
23785 322 }
23786 739 }
23787 1888 }
23788
23789 1888 void dragging_item()
23790 {
23791
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 1888 times.
2644 for(int32_t i=0; i<Lwpns.Count(); i++)
23792 {
23793 756 weapon *w = (weapon*)Lwpns.spr(i);
23794
23795
2/4
✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 756 times.
✗ Branch 3 not taken.
756 if((w->id == wBrang || w->id==wHookshot)&&itemsbuf[w->parentitem].flags & ITEM_FLAG5)//ITEM_FLAG5 is a port for qr_Z3BRANG_HSHOT
23796 {
23797 if(w->dragging>=0 && w->dragging<items.Count())
23798 {
23799 item* dragItem = (item*)items.spr(w->dragging);
23800 dragItem->x=w->x;
23801 dragItem->y=w->y;
23802
23803 // Drag the Fairy enemy as well as the Fairy item
23804 int32_t id = dragItem->id;
23805
23806 if(itemsbuf[id].family ==itype_fairy && itemsbuf[id].misc3)
23807 {
23808 movefairynew2(w->x,w->y,*dragItem);
23809 }
23810 }
23811 }
23812 756 }
23813 1888 }
23814
23815 int32_t more_carried_items()
23816 {
23817 int32_t hasmorecarries = 0;
23818
23819 for(int32_t i=0; i<items.Count(); i++)
23820 {
23821 if(((item*)items.spr(i))->pickup & ipENEMY)
23822 {
23823 hasmorecarries++;
23824 }
23825 }
23826
23827 return hasmorecarries;
23828 }
23829
23830 // messy code to do the enemy-carrying-the-item thing
23831 1888 void roaming_item()
23832 {
23833
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1888 if(!(hasitem&(4|2)) || !loaded_enemies)
23834 1888 return;
23835
23836 // All enemies already dead upon entering a room?
23837 if(guys.Count()==0)
23838 {
23839 return;
23840 }
23841
23842 // Lost track of the carrier?
23843 if(guycarryingitem<0 || guycarryingitem>=guys.Count() ||
23844 !((enemy*)guys.spr(guycarryingitem))->itemguy)
23845 {
23846 guycarryingitem=-1;
23847 for(int32_t j=0; j<guys.Count(); j++)
23848 {
23849 if(((enemy*)guys.spr(j))->itemguy)
23850 {
23851 guycarryingitem=j;
23852 break;
23853 }
23854 }
23855 }
23856
23857 if(hasitem&4)
23858 {
23859 guycarryingitem = -1;
23860
23861 for(int32_t i=0; i<guys.Count(); i++)
23862 {
23863 if(((enemy*)guys.spr(i))->itemguy)
23864 {
23865 guycarryingitem = i;
23866 }
23867 }
23868
23869 if(guycarryingitem == -1) //This happens when "default enemies" such as
23870 {
23871 return; //eSHOOTFBALL are alive but enemies from the list
23872 } //are not. Defer to HeroClass::checkspecial().
23873
23874 int32_t Item=tmpscr->item;
23875
23876 hasitem &= ~4;
23877
23878 if((!getmapflag(mITEM) || (tmpscr->flags9&fITEMRETURN)) && (tmpscr->hasitem != 0))
23879 {
23880 additem(0,0,Item,ipENEMY+ipONETIME+ipBIGRANGE
23881 + (((tmpscr->flags3&fHOLDITEM) || (itemsbuf[Item].family==itype_triforcepiece)) ? ipHOLDUP : 0)
23882 );
23883 hasitem |= 2;
23884 }
23885 else
23886 {
23887 return;
23888 }
23889 }
23890
23891 for(int32_t i=0; i<items.Count(); i++)
23892 {
23893 if(((item*)items.spr(i))->pickup&ipENEMY)
23894 {
23895 if(get_bit(quest_rules,qr_HIDECARRIEDITEMS))
23896 {
23897 items.spr(i)->x = -128; // Awfully inelegant, innit?
23898 items.spr(i)->y = -128;
23899 }
23900 else if(guycarryingitem>=0 && guycarryingitem<guys.Count())
23901 {
23902 if (!get_bit(quest_rules, qr_BROKEN_ITEM_CARRYING))
23903 {
23904 if (get_bit(quest_rules, qr_ENEMY_DROPS_USE_HITOFFSETS))
23905 {
23906 items.spr(i)->x = guys.spr(guycarryingitem)->x+guys.spr(guycarryingitem)->hxofs+(guys.spr(guycarryingitem)->hxsz/2)-8;
23907 items.spr(i)->y = guys.spr(guycarryingitem)->y+guys.spr(guycarryingitem)->hyofs+(guys.spr(guycarryingitem)->hysz/2)-10;
23908 }
23909 else
23910 {
23911 if(guys.spr(guycarryingitem)->extend >= 3)
23912 {
23913 items.spr(i)->x = guys.spr(guycarryingitem)->x+(guys.spr(guycarryingitem)->txsz-1)*8;
23914 items.spr(i)->y = guys.spr(guycarryingitem)->y-2+(guys.spr(guycarryingitem)->tysz-1)*8;
23915 }
23916 else
23917 {
23918 items.spr(i)->x = guys.spr(guycarryingitem)->x;
23919 items.spr(i)->y = guys.spr(guycarryingitem)->y - 2;
23920 }
23921 }
23922 items.spr(i)->z = guys.spr(guycarryingitem)->z;
23923 items.spr(i)->fakez = guys.spr(guycarryingitem)->fakez;
23924 }
23925 else
23926 {
23927 items.spr(i)->x = guys.spr(guycarryingitem)->x;
23928 items.spr(i)->y = guys.spr(guycarryingitem)->y - 2;
23929 items.spr(i)->fakez = guys.spr(guycarryingitem)->fakez;
23930 }
23931 }
23932 }
23933 }
23934 1888 }
23935
23936 bool enemy::IsBigAnim()
23937 {
23938 return (anim == a2FRMB || anim == a4FRM8EYEB || anim == a4FRM4EYEB
23939 || anim == a4FRM8DIRFB || anim == a4FRM4DIRB || anim == a4FRM4DIRFB
23940 || anim == a4FRM8DIRB);
23941 }
23942
23943 const char *old_guy_string[OLDMAXGUYS] =
23944 {
23945 "(None)","Abei","Ama","Merchant","Moblin","Fire","Fairy","Goriya","Zelda","Abei 2","Empty","","","","","","","","","",
23946 // 020
23947 "Octorok (L1, Slow)","Octorok (L2, Slow)","Octorok (L1, Fast)","Octorok (L2, Fast)","Tektite (L1)",
23948 // 025
23949 "Tektite (L2)","Leever (L1)","Leever (L2)","Moblin (L1)","Moblin (L2)",
23950 // 030
23951 "Lynel (L1)","Lynel (L2)","Peahat (L1)","Zora","Rock",
23952 // 035
23953 "Ghini (L1, Normal)","Ghini (L1, Phantom)","Armos","Keese (CSet 7)","Keese (CSet 8)",
23954 // 040
23955 "Keese (CSet 9)","Stalfos (L1)","Gel (L1, Normal)","Zol (L1, Normal)","Rope (L1)",
23956 // 045
23957 "Goriya (L1)","Goriya (L2)","Trap (4-Way)","Wall Master","Darknut (L1)",
23958 // 050
23959 "Darknut (L2)","Bubble (Sword, Temporary Disabling)","Vire (Normal)","Like Like","Gibdo",
23960 // 055
23961 "Pols Voice (Arrow)","Wizzrobe (Teleporting)","Wizzrobe (Floating)","Aquamentus (Facing Left)","Moldorm",
23962 // 060
23963 "Dodongo","Manhandla (L1)","Gleeok (1 Head)","Gleeok (2 Heads)","Gleeok (3 Heads)",
23964 // 065
23965 "Gleeok (4 Heads)","Digdogger (1 Kid)","Digdogger (3 Kids)","Digdogger Kid (1)","Digdogger Kid (2)",
23966 // 070
23967 "Digdogger Kid (3)","Digdogger Kid (4)","Gohma (L1)","Gohma (L2)","Lanmola (L1)",
23968 // 075
23969 "Lanmola (L2)","Patra (L1, Big Circle)","Patra (L1, Oval)","Ganon","Stalfos (L2)",
23970 // 080
23971 "Rope (L2)","Bubble (Sword, Permanent Disabling)","Bubble (Sword, Re-enabling)","Shooter (Fireball)","Item Fairy ",
23972 // 085
23973 "Fire","Octorok (Magic)", "Darknut (Death Knight)", "Gel (L1, Tribble)", "Zol (L1, Tribble)",
23974 // 090
23975 "Keese (Tribble)", "Vire (Tribble)", "Darknut (Splitting)", "Aquamentus (Facing Right)", "Manhandla (L2)",
23976 // 095
23977 "Trap (Horizontal, Line of Sight)", "Trap (Vertical, Line of Sight)", "Trap (Horizontal, Constant)", "Trap (Vertical, Constant)", "Wizzrobe (Fire)",
23978 // 100
23979 "Wizzrobe (Wind)", "Ceiling Master ", "Floor Master ", "Patra (BS Zelda)", "Patra (L2)",
23980 // 105
23981 "Patra (L3)", "Bat", "Wizzrobe (Bat)", "Wizzrobe (Bat 2) ", "Gleeok (Fire, 1 Head)",
23982 // 110
23983 "Gleeok (Fire, 2 Heads)", "Gleeok (Fire, 3 Heads)","Gleeok (Fire, 4 Heads)", "Wizzrobe (Mirror)", "Dodongo (BS Zelda)",
23984 // 115
23985 "Dodongo (Fire) ","Trigger", "Bubble (Item, Temporary Disabling)", "Bubble (Item, Permanent Disabling)", "Bubble (Item, Re-enabling)",
23986 // 120
23987 "Stalfos (L3)", "Gohma (L3)", "Gohma (L4)", "NPC 1 (Standing) ", "NPC 2 (Standing) ",
23988 // 125
23989 "NPC 3 (Standing) ", "NPC 4 (Standing) ", "NPC 5 (Standing) ", "NPC 6 (Standing) ", "NPC 1 (Walking) ",
23990 // 130
23991 "NPC 2 (Walking) ", "NPC 3 (Walking) ", "NPC 4 (Walking) ", "NPC 5 (Walking) ", "NPC 6 (Walking) ",
23992 // 135
23993 "Boulder", "Goriya (L3)", "Leever (L3)", "Octorok (L3, Slow)", "Octorok (L3, Fast)",
23994 // 140
23995 "Octorok (L4, Slow)", "Octorok (L4, Fast)", "Trap (8-Way) ", "Trap (Diagonal) ", "Trap (/, Constant) ",
23996 // 145
23997 "Trap (/, Line of Sight) ", "Trap (\\, Constant) ", "Trap (\\, Line of Sight) ", "Trap (CW, Constant) ", "Trap (CW, Line of Sight) ",
23998 // 150
23999 "Trap (CCW, Constant) ", "Trap (CCW, Line of Sight) ", "Wizzrobe (Summoner)", "Wizzrobe (Ice) ", "Shooter (Magic)",
24000 // 155
24001 "Shooter (Rock)", "Shooter (Spear)", "Shooter (Sword)", "Shooter (Fire)", "Shooter (Fire 2)",
24002 // 160
24003 "Bombchu", "Gel (L2, Normal)", "Zol (L2, Normal)", "Gel (L2, Tribble)", "Zol (L2, Tribble)",
24004 // 165
24005 "Tektite (L3) ", "Spinning Tile (Combo)", "Spinning Tile (Enemy Sprite)", "Lynel (L3) ", "Peahat (L2) ",
24006 // 170
24007 "Pols Voice (Magic) ", "Pols Voice (Whistle) ", "Darknut (Mirror) ", "Ghini (L2, Fire) ", "Ghini (L2, Magic) ",
24008 // 175
24009 "Grappler Bug (HP) ", "Grappler Bug (MP) "
24010 };
24011
24012 /*** end of guys.cc ***/
24013
24014